This commit was generated by cvs2svn to compensate for changes in r16049,

which included commits to RCS files with non-trunk default branches.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/libobjc/trunk@16050 72102866-910b-0410-8b05-ffd578937521
main
fedor 23 years ago
parent eeb9393578
commit 5c8c6241e1

@ -22,21 +22,28 @@
#Makefile.in files. Some of this stuff may be unnecessary and #Makefile.in files. Some of this stuff may be unnecessary and
#worthless. #worthless.
SHELL = /bin/sh SHELL = @SHELL@
MAKEOVERRIDES=
#### Start of system configuration section. #### #### Start of system configuration section. ####
srcdir = @srcdir@ srcdir = @glibcpp_srcdir@
VPATH = @srcdir@ VPATH = @glibcpp_srcdir@
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
target_alias = @target_alias@ target_alias = @target_alias@
gcc_version = @gcc_version@ gcc_version = @gcc_version@
gcc_version_trigger = @gcc_version_trigger@ gcc_version_trigger = @gcc_version_trigger@
top_srcdir = @top_srcdir@
toplevel_srcdir = @toplevel_srcdir@
toolexecdir = @glibcpp_toolexecdir@
glibcpp_toolexecdir = @glibcpp_toolexecdir@
glibcpp_toolexeclibdir = @glibcpp_toolexeclibdir@
top_builddir = .
libdir = $(exec_prefix)/lib libdir = $(exec_prefix)/lib
libsubdir = $(libdir)/gcc-lib/$(target_alias)/$(gcc_version) libsubdir = $(libdir)/gcc-lib/$(target_alias)/$(gcc_version)
incinstalldir = $(libsubdir)/include
# Multilib support variables. # Multilib support variables.
MULTISRCTOP = MULTISRCTOP =
@ -60,8 +67,9 @@ RANLIB = @RANLIB@
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
WARN_CFLAGS = -W -Wall -Wwrite-strings -Wstrict-prototypes
GTHREAD_FLAGS=@GTHREAD_FLAGS@ GTHREAD_FLAGS=@GTHREAD_FLAGS@
ALL_CFLAGS = -I. -I$(srcdir) $(CPPFLAGS) $(DEFS) $(CFLAGS) \ ALL_CFLAGS = -I. -I$(srcdir) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(WARN_CFLAGS) \
$(GTHREAD_FLAGS) -DIN_GCC -DIN_TARGET_LIBS $(GTHREAD_FLAGS) -DIN_GCC -DIN_TARGET_LIBS
# Libtool # Libtool
@ -110,6 +118,7 @@ FLAGS_TO_PASS = \
"AR_FLAGS=$(AR_FLAGS)" \ "AR_FLAGS=$(AR_FLAGS)" \
"CC=$(CC)" \ "CC=$(CC)" \
"CFLAGS=$(CFLAGS)" \ "CFLAGS=$(CFLAGS)" \
"DESTDIR=$(DESTDIR)" \
"LIBCFLAGS=$(LIBCFLAGS)" \ "LIBCFLAGS=$(LIBCFLAGS)" \
"EXTRA_OFILES=$(EXTRA_OFILES)" \ "EXTRA_OFILES=$(EXTRA_OFILES)" \
"HDEFINES=$(HDEFINES)" \ "HDEFINES=$(HDEFINES)" \
@ -129,7 +138,7 @@ FLAGS_TO_PASS = \
"tooldir=$(tooldir)" "tooldir=$(tooldir)"
all: libobjc.la $(OBJC_BOEHM_GC) all: libobjc.la $(OBJC_BOEHM_GC)
$(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=all : $(MAKE) ; exec $(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=all
# User-visible header files. # User-visible header files.
@ -253,11 +262,13 @@ $(OBJC_THREAD_FILE)_gc.lo: $(OBJC_THREAD_FILE).c
doc: info dvi html doc: info dvi html
libobjc.la: $(OBJS) libobjc.la: $(OBJS)
$(LIBTOOL_LINK) $(CC) -o $@ $(OBJS) -rpath $(libsubdir) \ $(LIBTOOL_LINK) $(CC) -o $@ $(OBJS) \
-rpath $(glibcpp_toolexeclibdir) \
-version-info $(LIBOBJC_VERSION) -version-info $(LIBOBJC_VERSION)
libobjc_gc.la: $(OBJS_GC) libobjc_gc.la: $(OBJS_GC)
$(LIBTOOL_LINK) $(CC) -o $@ $(OBJS_GC) -rpath $(libsubdir) \ $(LIBTOOL_LINK) $(CC) -o $@ $(OBJS_GC) \
-rpath $(glibcpp_toolexeclibdir) \
-version-info $(LIBOBJC_GC_VERSION) -version-info $(LIBOBJC_GC_VERSION)
# #
@ -289,18 +300,9 @@ libobjc.dll: libobjc_s.a libobjc_entry.o
# #
# #
info: objc-features.info info:
dvi: objc-features.dvi dvi:
html: objc-features_toc.html html:
objc-features.info: $(srcdir)/objc-features.texi
makeinfo -I$(srcdir) $(srcdir)/objc-features.texi
objc-features.dvi: $(srcdir)/objc-features.texi
TEXINPUTS="$(srcdir):${TEXINPUTS}" texi2dvi $(srcdir)/objc-features.texi
objc-features_toc.html: objc-features.texi
texi2html -split_node $(srcdir)/objc-features.texi
Makefile: Makefile.in config.status Makefile: Makefile.in config.status
$(SHELL) config.status $(SHELL) config.status
@ -314,24 +316,24 @@ ${srcdir}/configure: configure.in
rm -f config.cache rm -f config.cache
cd ${srcdir} && autoconf cd ${srcdir} && autoconf
install: install-libs copy-headers install: install-libs install-headers
install-libs: installdirs install-libs: installdirs
$(LIBTOOL_INSTALL) $(INSTALL_DATA) libobjc.la $(libsubdir)/libobjc.la; $(SHELL) $(toplevel_srcdir)/mkinstalldirs $(DESTDIR)$(glibcpp_toolexeclibdir)
$(LIBTOOL_INSTALL) $(INSTALL) libobjc.la $(DESTDIR)$(glibcpp_toolexeclibdir);
if [ "$(OBJC_BOEHM_GC)" ]; then \ if [ "$(OBJC_BOEHM_GC)" ]; then \
$(LIBTOOL_INSTALL) $(INSTALL_DATA) libobjc_gc.la \ $(LIBTOOL_INSTALL) $(INSTALL) libobjc_gc.la \
$(libsubdir)/libobjc_gc.la;\ $(DESTDIR)$(glibcpp_toolexeclibdir);\
fi fi
$(MULTIDO) $(FLAGS_TO_PASS) multi-do DO="$@"
@-$(LIBTOOL) --mode=finish $(DESTDIR)$(glibcpp_toolexeclibdir)
# Copy Objective C headers to installation include directory. # Copy Objective C headers to installation include directory.
copy-headers: install-headers:
-rm -rf $(incinstalldir)/objc $(SHELL) $(toplevel_srcdir)/mkinstalldirs $(DESTDIR)$(libsubdir)/include/objc
-mkdir $(incinstalldir)/objc
-chmod a+rx $(incinstalldir)/objc
for file in $(OBJC_H); do \ for file in $(OBJC_H); do \
realfile=$(srcdir)/objc/$${file}; \ realfile=$(srcdir)/objc/$${file}; \
cp $${realfile} $(incinstalldir)/objc; \ $(INSTALL_DATA) $${realfile} $(DESTDIR)$(libsubdir)/include/objc; \
chmod a+r $(incinstalldir)/objc/$${file}; \
done done
check uninstall install-strip dist installcheck installdirs: check uninstall install-strip dist installcheck installdirs:

@ -1,5 +1,5 @@
/* The implementation of class Object for Objective-C. /* The implementation of class Object for Objective-C.
Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. Copyright (C) 1993, 1994, 1995, 1997, 2002 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
@ -199,7 +199,7 @@ extern int errno;
+ (BOOL) conformsTo: (Protocol*)aProtocol + (BOOL) conformsTo: (Protocol*)aProtocol
{ {
int i; size_t i;
struct objc_protocol_list* proto_list; struct objc_protocol_list* proto_list;
id parent; id parent;
@ -271,6 +271,7 @@ extern int errno;
- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame - (retval_t)forward:(SEL)aSel :(arglist_t)argFrame
{ {
(void) argFrame; /* UNUSED */
return (retval_t)[self doesNotRecognize: aSel]; return (retval_t)[self doesNotRecognize: aSel];
} }
@ -364,12 +365,14 @@ extern int errno;
- read: (TypedStream*)aStream - read: (TypedStream*)aStream
{ {
(void) aStream; /* UNUSED */
// [super read: aStream]; // [super read: aStream];
return self; return self;
} }
- write: (TypedStream*)aStream - write: (TypedStream*)aStream
{ {
(void) aStream; /* UNUSED */
// [super write: aStream]; // [super write: aStream];
return self; return self;
} }

@ -53,7 +53,7 @@ struct objc_method_description_list {
- (BOOL) conformsTo: (Protocol *)aProtocolObject - (BOOL) conformsTo: (Protocol *)aProtocolObject
{ {
int i; size_t i;
struct objc_protocol_list* proto_list; struct objc_protocol_list* proto_list;
if (!strcmp(aProtocolObject->protocol_name, self->protocol_name)) if (!strcmp(aProtocolObject->protocol_name, self->protocol_name))
@ -88,9 +88,10 @@ struct objc_method_description_list {
for (proto_list = protocol_list; proto_list; proto_list = proto_list->next) for (proto_list = protocol_list; proto_list; proto_list = proto_list->next)
{ {
for (i=0; i < proto_list->count; i++) size_t j;
for (j=0; j < proto_list->count; j++)
{ {
if ((result = [proto_list->list[i] if ((result = [proto_list->list[j]
descriptionForInstanceMethod: aSel])) descriptionForInstanceMethod: aSel]))
return result; return result;
} }
@ -114,9 +115,10 @@ struct objc_method_description_list {
for (proto_list = protocol_list; proto_list; proto_list = proto_list->next) for (proto_list = protocol_list; proto_list; proto_list = proto_list->next)
{ {
for (i=0; i < proto_list->count; i++) size_t j;
for (j=0; j < proto_list->count; j++)
{ {
if ((result = [proto_list->list[i] if ((result = [proto_list->list[j]
descriptionForClassMethod: aSel])) descriptionForClassMethod: aSel]))
return result; return result;
} }

@ -102,30 +102,33 @@ high degree of portability across platforms.
The backend is composed of a file with the necessary code to map the ObjC The backend is composed of a file with the necessary code to map the ObjC
thread and mutex to a platform specific implementation. For example, the thread and mutex to a platform specific implementation. For example, the
file thr-solaris.c contains the implementation for Solaris. When you file thr-solaris.c contains the implementation for Solaris.
configure GCC, it attempts to pick an appropriate backend file for the
target platform; however, you can override this choice by assign the If you are compiling libobjc as part of GCC, the thr-objc.c backend is
OBJC_THREAD_FILE make variable to the basename of the backend file. This always used; this backend uses GCC's gthread code. The thread system
is especially useful on platforms which have multiple thread libraries. is automatically configured when GCC is configured. Important: make
For example: sure you configure GCC using `--enable-threads' if you want threads !
make OBJC_THREAD_FILE=thr-posix If you want to compile libobjc standalone, then you would need to
modify the configure.in and makefiles for it; and you need to pick an
would indicate that the generic posix backend file, thr-posix.c, should be appropriate backend file for the target platform; you make this choice
compiled with the ObjC runtime library. If your platform does not support by assigning the OBJC_THREAD_FILE make variable to the basename of the
threads then you should specify the OBJC_THREAD_FILE=thr-single backend file backend file. For example, OBJC_THREAD_FILE=thr-posix would indicate
to compile the ObjC runtime library without thread or mutex support; note that the generic posix backend file, thr-posix.c, should be compiled
that programs which rely upon the ObjC thread and mutex functions will with the ObjC runtime library. If your platform does not support
compile and link correctly but attempting to create a thread or mutex will threads then you should specify the OBJC_THREAD_FILE=thr-single
result in an error. backend file to compile the ObjC runtime library without thread or
mutex support; note that programs which rely upon the ObjC thread and
mutex functions will compile and link correctly but attempting to
create a thread or mutex will result in an error.
It is questionable whether it is really necessary to have both a It is questionable whether it is really necessary to have both a
frontend and backend function for all available functionality. On the frontend and backend function for all available functionality. On the
one hand, it provides a clear, consistent differentiation between what one hand, it provides a clear, consistent differentiation between what
is public and what is private with the downside of having the overhead is public and what is private with the downside of having the overhead
of multiple functions calls. For example, the function to have a thread of multiple functions calls. For example, the function to have a
yield the processor is objc_thread_yield; in the current implementation thread yield the processor is objc_thread_yield; in the current
this produces a function call set: implementation this produces a function call set:
objc_thread_yield() -> __objc_thread_yield() -> system yield function objc_thread_yield() -> __objc_thread_yield() -> system yield function

231
aclocal.m4 vendored

@ -1,2 +1,231 @@
# Just a clone of ../libtool.m4. dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
dnl
dnl Initialize configure bits.
dnl
dnl GLIBCPP_TOPREL_CONFIGURE
AC_DEFUN(GLIBCPP_TOPREL_CONFIGURE, [
dnl Default to --enable-multilib
AC_ARG_ENABLE(multilib,
[ --enable-multilib build hella library versions (default)],
[case "${enableval}" in
yes) multilib=yes ;;
no) multilib=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
esac], [multilib=yes])dnl
# When building with srcdir == objdir, links to the source files will
# be created in directories within the target_subdir. We have to
# adjust toplevel_srcdir accordingly, so that configure finds
# install-sh and other auxiliary files that live in the top-level
# source directory.
if test "${srcdir}" = "."; then
if test -z "${with_target_subdir}"; then
toprel=".."
else
if test "${with_target_subdir}" != "."; then
toprel="${with_multisrctop}../.."
else
toprel="${with_multisrctop}.."
fi
fi
else
toprel=".."
fi
AC_CONFIG_AUX_DIR(${srcdir}/$toprel)
toplevel_srcdir=\${top_srcdir}/$toprel
AC_SUBST(toplevel_srcdir)
])
dnl
dnl Initialize configure bits.
dnl
dnl GLIBCPP_CONFIGURE
AC_DEFUN(GLIBCPP_CONFIGURE, [
# Export build and source directories.
# These need to be absolute paths, yet at the same time need to
# canonicalize only relative paths, because then amd will not unmount
# drives. Thus the use of PWDCMD: set it to 'pawd' or 'amq -w' if using amd.
glibcpp_builddir=`${PWDCMD-pwd}`
case $srcdir in
[\\/$]* | ?:[\\/]*) glibcpp_srcdir=${srcdir} ;;
*) glibcpp_srcdir=`cd "$srcdir" && ${PWDCMD-pwd} || echo "$srcdir"` ;;
esac
AC_SUBST(glibcpp_builddir)
AC_SUBST(glibcpp_srcdir)
dnl This is here just to satisfy automake.
ifelse(not,equal,[AC_CONFIG_AUX_DIR(..)])
# Will set LN_S to either 'ln -s' or 'ln'. With autoconf 2.50+, can also
# be 'cp -p' if linking isn't available.
#ac_cv_prog_LN_S='cp -p'
AC_PROG_LN_S
# We use these options to decide which functions to include.
AC_ARG_WITH(target-subdir,
[ --with-target-subdir=SUBDIR
configuring in a subdirectory])
AC_ARG_WITH(cross-host,
[ --with-cross-host=HOST configuring with a cross compiler])
# Never versions of autoconf add an underscore to these functions.
# Prevent future problems ...
ifdef([AC_PROG_CC_G],[],[define([AC_PROG_CC_G],defn([_AC_PROG_CC_G]))])
ifdef([AC_PROG_CC_GNU],[],[define([AC_PROG_CC_GNU],defn([_AC_PROG_CC_GNU]))])
ifdef([AC_PROG_CXX_G],[],[define([AC_PROG_CXX_G],defn([_AC_PROG_CXX_G]))])
ifdef([AC_PROG_CXX_GNU],[],[define([AC_PROG_CXX_GNU],defn([_AC_PROG_CXX_GNU]))])
# AC_PROG_CC
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(LIB_AC_PROG_CC,
[AC_BEFORE([$0], [AC_PROG_CPP])dnl
dnl Fool anybody using AC_PROG_CC.
AC_PROVIDE([AC_PROG_CC])
AC_CHECK_PROG(CC, gcc, gcc)
if test -z "$CC"; then
AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
fi
AC_PROG_CC_GNU
if test $ac_cv_prog_gcc = yes; then
GCC=yes
dnl Check whether -g works, even if CFLAGS is set, in case the package
dnl plays around with CFLAGS (such as to build both debugging and
dnl normal versions of a library), tasteless as that idea is.
ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
AC_PROG_CC_G
if test "$ac_test_CFLAGS" = set; then
CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-O2"
fi
else
GCC=
test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
])
LIB_AC_PROG_CC
AC_CHECK_TOOL(AS, as)
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, ranlib-not-found-in-path-error)
AC_PROG_INSTALL
# We need AC_EXEEXT to keep automake happy in cygnus mode. However,
# at least currently, we never actually build a program, so we never
# need to use $(EXEEXT). Moreover, the test for EXEEXT normally
# fails, because we are probably configuring with a cross compiler
# which can't create executables. So we include AC_EXEEXT to keep
# automake happy, but we don't execute it, since we don't care about
# the result.
if false; then
# autoconf 2.50 runs AC_EXEEXT by default, and the macro expands
# to nothing, so nothing would remain between `then' and `fi' if it
# were not for the `:' below.
:
AC_EXEEXT
fi
])
dnl
dnl GLIBCPP_EXPORT_INSTALL_INFO
dnl calculates gxx_install_dir
dnl exports glibcpp_toolexecdir
dnl exports glibcpp_toolexeclibdir
dnl exports glibcpp_prefixdir
dnl
dnl Assumes cross_compiling bits already done, and with_cross_host in
dnl particular
dnl
dnl GLIBCPP_EXPORT_INSTALL_INFO
AC_DEFUN(GLIBCPP_EXPORT_INSTALL_INFO, [
# Assumes glibcpp_builddir, glibcpp_srcdir are alreay set up and
# exported correctly in GLIBCPP_CONFIGURE.
glibcpp_toolexecdir=no
glibcpp_toolexeclibdir=no
glibcpp_prefixdir=${prefix}
AC_MSG_CHECKING([for interface version number])
libstdcxx_interface=$INTERFACE
AC_MSG_RESULT($libstdcxx_interface)
# Process the option "--enable-version-specific-runtime-libs"
AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
AC_ARG_ENABLE(version-specific-runtime-libs,
[ --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory ],
[case "$enableval" in
yes) version_specific_libs=yes ;;
no) version_specific_libs=no ;;
*) AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs]);;
esac],
version_specific_libs=no)dnl
# Option set, now we can test it.
AC_MSG_RESULT($version_specific_libs)
gcc_version_trigger=${srcdir}/../gcc/version.c
gcc_version_full=`grep version_string ${gcc_version_trigger} | sed -e 's/.*\"\([[^ \"]]*\)[[ \"]].*/\1/'`
gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'`
AC_SUBST(gcc_version)
AC_SUBST(gcc_version_trigger)
if test $version_specific_libs = yes; then
# Need the gcc compiler version to know where to install libraries
# and header files if --enable-version-specific-runtime-libs option
# is selected.
changequote(,)dnl
glibcpp_toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
glibcpp_toolexeclibdir='$(toolexecdir)/'${gcc_version}'$(MULTISUBDIR)'
changequote([,])dnl
fi
# Calculate glibcpp_toolexecdir, glibcpp_toolexeclibdir
# Install a library built with a cross compiler in tooldir, not libdir.
if test x"$glibcpp_toolexecdir" = x"no"; then
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
glibcpp_toolexecdir='$(exec_prefix)/$(target_alias)'
glibcpp_toolexeclibdir='$(toolexecdir)/lib'
else
glibcpp_toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
glibcpp_toolexeclibdir='$(libdir)'
fi
glibcpp_toolexeclibdir=$glibcpp_toolexeclibdir/`$CC -print-multi-os-directory`
fi
AC_SUBST(glibcpp_prefixdir)
AC_SUBST(glibcpp_toolexecdir)
AC_SUBST(glibcpp_toolexeclibdir)
])
sinclude(../libtool.m4) sinclude(../libtool.m4)
dnl The lines below arrange for aclocal not to bring an installed
dnl libtool.m4 into aclocal.m4, while still arranging for automake to
dnl add a definition of LIBTOOL to Makefile.in.
ifelse(,,,[AC_SUBST(LIBTOOL)
AC_DEFUN([AM_PROG_LIBTOOL])
AC_DEFUN([AC_LIBTOOL_DLOPEN])
AC_DEFUN([AC_PROG_LD])
])

File diff suppressed because it is too large Load Diff

@ -1,7 +1,11 @@
/* GNU Objective C Runtime class related functions /* GNU Objective C Runtime class related functions
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. Copyright (C) 1993, 1995, 1996, 1997, 2001, 2002
Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup and Dennis Glatting. Contributed by Kresten Krab Thorup and Dennis Glatting.
Lock-free class table code designed and written from scratch by
Nicola Pero, 2001.
This file is part of GNU CC. This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify it under the GNU CC is free software; you can redistribute it and/or modify it under the
@ -23,135 +27,490 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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 "runtime.h" /* the kitchen sink */ /*
The code in this file critically affects class method invocation
speed. This long preamble comment explains why, and the issues
involved.
One of the traditional weaknesses of the GNU Objective-C runtime is
that class method invocations are slow. The reason is that when you
write
array = [NSArray new];
this gets basically compiled into the equivalent of
array = [(objc_get_class ("NSArray")) new];
objc_get_class returns the class pointer corresponding to the string
`NSArray'; and because of the lookup, the operation is more
complicated and slow than a simple instance method invocation.
Most high performance Objective-C code (using the GNU Objc runtime)
I had the opportunity to read (or write) work around this problem by
caching the class pointer:
Class arrayClass = [NSArray class];
... later on ...
array = [arrayClass new];
array = [arrayClass new];
array = [arrayClass new];
In this case, you always perform a class lookup (the first one), but
then all the [arrayClass new] methods run exactly as fast as an
instance method invocation. It helps if you have many class method
invocations to the same class.
The long-term solution to this problem would be to modify the
compiler to output tables of class pointers corresponding to all the
class method invocations, and to add code to the runtime to update
these tables - that should in the end allow class method invocations
to perform precisely as fast as instance method invocations, because
no class lookup would be involved. I think the Apple Objective-C
runtime uses this technique. Doing this involves synchronized
modifications in the runtime and in the compiler.
As a first medicine to the problem, I [NP] have redesigned and
rewritten the way the runtime is performing class lookup. This
doesn't give as much speed as the other (definitive) approach, but
at least a class method invocation now takes approximately 4.5 times
an instance method invocation on my machine (it would take approx 12
times before the rewriting), which is a lot better.
One of the main reason the new class lookup is so faster is because
I implemented it in a way that can safely run multithreaded without
using locks - a so-called `lock-free' data structure. The atomic
operation is pointer assignment. The reason why in this problem
lock-free data structures work so well is that you never remove
classes from the table - and the difficult thing with lock-free data
structures is freeing data when is removed from the structures. */
#include "runtime.h" /* the kitchen sink */
#include "sarray.h" #include "sarray.h"
/* The table of classname->class. Used for objc_lookup_class and friends */ #include <objc/objc.h>
static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */ #include <objc/objc-api.h>
#include <objc/thr.h>
/* This is a hook which is called by objc_get_class and /* We use a table which maps a class name to the corresponding class
objc_lookup_class if the runtime is not able to find the class. * pointer. The first part of this file defines this table, and
This may e.g. try to load in the class using dynamic loading */ * functions to do basic operations on the table. The second part of
Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */ * the file implements some higher level Objective-C functionality for
* classes by using the functions provided in the first part to manage
* the table. */
/**
** Class Table Internals
**/
/* True when class links has been resolved */ /* A node holding a class */
BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */ typedef struct class_node
{
struct class_node *next; /* Pointer to next entry on the list.
NULL indicates end of list. */
const char *name; /* The class name string */
int length; /* The class name string length */
Class pointer; /* The Class pointer */
} *class_node_ptr;
/* A table containing classes is a class_node_ptr (pointing to the
first entry in the table - if it is NULL, then the table is
empty). */
/* We have 1024 tables. Each table contains all class names which
have the same hash (which is a number between 0 and 1023). To look
up a class_name, we compute its hash, and get the corresponding
table. Once we have the table, we simply compare strings directly
till we find the one which we want (using the length first). The
number of tables is quite big on purpose (a normal big application
has less than 1000 classes), so that you shouldn't normally get any
collisions, and get away with a single comparison (which we can't
avoid since we need to know that you have got the right thing). */
#define CLASS_TABLE_SIZE 1024
#define CLASS_TABLE_MASK 1023
static class_node_ptr class_table_array[CLASS_TABLE_SIZE];
/* The table writing mutex - we lock on writing to avoid conflicts
between different writers, but we read without locks. That is
possible because we assume pointer assignment to be an atomic
operation. */
static objc_mutex_t __class_table_lock = NULL;
/* CLASS_TABLE_HASH is how we compute the hash of a class name. It is
a macro - *not* a function - arguments *are* modified directly.
INDEX should be a variable holding an int;
HASH should be a variable holding an int;
CLASS_NAME should be a variable holding a (char *) to the class_name.
After the macro is executed, INDEX contains the length of the
string, and HASH the computed hash of the string; CLASS_NAME is
untouched. */
#define CLASS_TABLE_HASH(INDEX, HASH, CLASS_NAME) \
HASH = 0; \
for (INDEX = 0; CLASS_NAME[INDEX] != '\0'; INDEX++) \
{ \
HASH = (HASH << 4) ^ (HASH >> 28) ^ CLASS_NAME[INDEX]; \
} \
\
HASH = (HASH ^ (HASH >> 10) ^ (HASH >> 20)) & CLASS_TABLE_MASK;
/* Setup the table. */
static void
class_table_setup (void)
{
/* Start - nothing in the table. */
memset (class_table_array, 0, sizeof (class_node_ptr) * CLASS_TABLE_SIZE);
/* The table writing mutex. */
__class_table_lock = objc_mutex_allocate ();
}
/* Initial number of buckets size of class hash table. */
#define CLASS_HASH_SIZE 32
void __objc_init_class_tables() /* Insert a class in the table (used when a new class is registered). */
static void
class_table_insert (const char *class_name, Class class_pointer)
{ {
/* Allocate the class hash table */ int hash, length;
class_node_ptr new_node;
if(__objc_class_hash) /* Find out the class name's hash and length. */
return; CLASS_TABLE_HASH (length, hash, class_name);
/* Prepare the new node holding the class. */
new_node = objc_malloc (sizeof (struct class_node));
new_node->name = class_name;
new_node->length = length;
new_node->pointer = class_pointer;
/* Lock the table for modifications. */
objc_mutex_lock (__class_table_lock);
/* Insert the new node in the table at the beginning of the table at
class_table_array[hash]. */
new_node->next = class_table_array[hash];
class_table_array[hash] = new_node;
objc_mutex_unlock (__class_table_lock);
}
objc_mutex_lock(__objc_runtime_mutex); /* Replace a class in the table (used only by poseAs:). */
static void
class_table_replace (Class old_class_pointer, Class new_class_pointer)
{
int hash;
class_node_ptr node;
__objc_class_hash objc_mutex_lock (__class_table_lock);
= hash_new (CLASS_HASH_SIZE,
(hash_func_type) hash_string, hash = 0;
(compare_func_type) compare_strings); node = class_table_array[hash];
while (hash < CLASS_TABLE_SIZE)
{
if (node == NULL)
{
hash++;
if (hash < CLASS_TABLE_SIZE)
{
node = class_table_array[hash];
}
}
else
{
Class class1 = node->pointer;
objc_mutex_unlock(__objc_runtime_mutex); if (class1 == old_class_pointer)
{
node->pointer = new_class_pointer;
}
node = node->next;
}
}
objc_mutex_unlock (__class_table_lock);
}
/* Get a class from the table. This does not need mutex protection.
Currently, this function is called each time you call a static
method, this is why it must be very fast. */
static inline Class
class_table_get_safe (const char *class_name)
{
class_node_ptr node;
int length, hash;
/* Compute length and hash. */
CLASS_TABLE_HASH (length, hash, class_name);
node = class_table_array[hash];
if (node != NULL)
{
do
{
if (node->length == length)
{
/* Compare the class names. */
int i;
for (i = 0; i < length; i++)
{
if ((node->name)[i] != class_name[i])
{
break;
}
}
if (i == length)
{
/* They are equal! */
return node->pointer;
}
}
}
while ((node = node->next) != NULL);
}
return Nil;
}
/* Enumerate over the class table. */
struct class_table_enumerator
{
int hash;
class_node_ptr node;
};
static Class
class_table_next (struct class_table_enumerator **e)
{
struct class_table_enumerator *enumerator = *e;
class_node_ptr next;
if (enumerator == NULL)
{
*e = objc_malloc (sizeof (struct class_table_enumerator));
enumerator = *e;
enumerator->hash = 0;
enumerator->node = NULL;
next = class_table_array[enumerator->hash];
}
else
{
next = enumerator->node->next;
}
if (next != NULL)
{
enumerator->node = next;
return enumerator->node->pointer;
}
else
{
enumerator->hash++;
while (enumerator->hash < CLASS_TABLE_SIZE)
{
next = class_table_array[enumerator->hash];
if (next != NULL)
{
enumerator->node = next;
return enumerator->node->pointer;
}
enumerator->hash++;
}
/* Ok - table finished - done. */
objc_free (enumerator);
return Nil;
}
}
#if 0 /* DEBUGGING FUNCTIONS */
/* Debugging function - print the class table. */
void
class_table_print (void)
{
int i;
for (i = 0; i < CLASS_TABLE_SIZE; i++)
{
class_node_ptr node;
printf ("%d:\n", i);
node = class_table_array[i];
while (node != NULL)
{
printf ("\t%s\n", node->name);
node = node->next;
}
}
}
/* Debugging function - print an histogram of number of classes in
function of hash key values. Useful to evaluate the hash function
in real cases. */
void
class_table_print_histogram (void)
{
int i, j;
int counter = 0;
for (i = 0; i < CLASS_TABLE_SIZE; i++)
{
class_node_ptr node;
node = class_table_array[i];
while (node != NULL)
{
counter++;
node = node->next;
}
if (((i + 1) % 50) == 0)
{
printf ("%4d:", i + 1);
for (j = 0; j < counter; j++)
{
printf ("X");
}
printf ("\n");
counter = 0;
}
}
printf ("%4d:", i + 1);
for (j = 0; j < counter; j++)
{
printf ("X");
}
printf ("\n");
}
#endif /* DEBUGGING FUNCTIONS */
/**
** Objective-C runtime functions
**/
/* From now on, the only access to the class table data structure
should be via the class_table_* functions. */
/* This is a hook which is called by objc_get_class and
objc_lookup_class if the runtime is not able to find the class.
This may e.g. try to load in the class using dynamic loading. */
Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */
/* True when class links has been resolved. */
BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
void
__objc_init_class_tables (void)
{
/* Allocate the class hash table. */
if (__class_table_lock)
return;
objc_mutex_lock (__objc_runtime_mutex);
class_table_setup ();
objc_mutex_unlock (__objc_runtime_mutex);
} }
/* This function adds a class to the class hash table, and assigns the /* This function adds a class to the class hash table, and assigns the
class a number, unless it's already known */ class a number, unless it's already known. */
void void
__objc_add_class_to_hash(Class class) __objc_add_class_to_hash (Class class)
{ {
Class h_class; Class h_class;
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
/* make sure the table is there */ /* Make sure the table is there. */
assert(__objc_class_hash); assert (__class_table_lock);
/* make sure it's not a meta class */ /* Make sure it's not a meta class. */
assert(CLS_ISCLASS(class)); assert (CLS_ISCLASS (class));
/* Check to see if the class is already in the hash table. */ /* Check to see if the class is already in the hash table. */
h_class = hash_value_for_key (__objc_class_hash, class->name); h_class = class_table_get_safe (class->name);
if (!h_class) if (! h_class)
{ {
/* The class isn't in the hash table. Add the class and assign a class /* The class isn't in the hash table. Add the class and assign a class
number. */ number. */
static unsigned int class_number = 1; static unsigned int class_number = 1;
CLS_SETNUMBER(class, class_number); CLS_SETNUMBER (class, class_number);
CLS_SETNUMBER(class->class_pointer, class_number); CLS_SETNUMBER (class->class_pointer, class_number);
++class_number; ++class_number;
hash_add (&__objc_class_hash, class->name, class); class_table_insert (class->name, class);
} }
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
/* Get the class object for the class named NAME. If NAME does not /* Get the class object for the class named NAME. If NAME does not
identify a known class, the hook _objc_lookup_class is called. If identify a known class, the hook _objc_lookup_class is called. If
this fails, nil is returned */ this fails, nil is returned. */
Class objc_lookup_class (const char* name) Class
objc_lookup_class (const char *name)
{ {
Class class; Class class;
objc_mutex_lock(__objc_runtime_mutex); class = class_table_get_safe (name);
/* Make sure the class hash table exists. */
assert (__objc_class_hash);
class = hash_value_for_key (__objc_class_hash, name);
objc_mutex_unlock(__objc_runtime_mutex);
if (class) if (class)
return class; return class;
if (_objc_lookup_class) if (_objc_lookup_class)
return (*_objc_lookup_class)(name); return (*_objc_lookup_class) (name);
else else
return 0; return 0;
} }
/* Get the class object for the class named NAME. If NAME does not /* Get the class object for the class named NAME. If NAME does not
identify a known class, the hook _objc_lookup_class is called. If identify a known class, the hook _objc_lookup_class is called. If
this fails, an error message is issued and the system aborts */ this fails, an error message is issued and the system aborts. */
Class Class
objc_get_class (const char *name) objc_get_class (const char *name)
{ {
Class class; Class class;
objc_mutex_lock(__objc_runtime_mutex); class = class_table_get_safe (name);
/* Make sure the class hash table exists. */
assert (__objc_class_hash);
class = hash_value_for_key (__objc_class_hash, name);
objc_mutex_unlock(__objc_runtime_mutex);
if (class) if (class)
return class; return class;
if (_objc_lookup_class) if (_objc_lookup_class)
class = (*_objc_lookup_class)(name); class = (*_objc_lookup_class) (name);
if(class) if (class)
return class; return class;
objc_error(nil, OBJC_ERR_BAD_CLASS, objc_error (nil, OBJC_ERR_BAD_CLASS,
"objc runtime: cannot find class %s\n", name); "objc runtime: cannot find class %s\n", name);
return 0; return 0;
} }
MetaClass MetaClass
objc_get_meta_class(const char *name) objc_get_meta_class (const char *name)
{ {
return objc_get_class(name)->class_pointer; return objc_get_class (name)->class_pointer;
} }
/* This function provides a way to enumerate all the classes in the /* This function provides a way to enumerate all the classes in the
@ -160,58 +519,57 @@ objc_get_meta_class(const char *name)
For example: For example:
id class; id class;
void *es = NULL; void *es = NULL;
while ((class = objc_next_class(&es))) while ((class = objc_next_class (&es)))
... do something with class; ... do something with class;
*/ */
Class Class
objc_next_class(void **enum_state) objc_next_class (void **enum_state)
{ {
objc_mutex_lock(__objc_runtime_mutex); Class class;
/* make sure the table is there */
assert(__objc_class_hash);
*(node_ptr*)enum_state = objc_mutex_lock (__objc_runtime_mutex);
hash_next(__objc_class_hash, *(node_ptr*)enum_state);
/* Make sure the table is there. */
assert (__class_table_lock);
objc_mutex_unlock(__objc_runtime_mutex); class = class_table_next ((struct class_table_enumerator **) enum_state);
if (*(node_ptr*)enum_state) objc_mutex_unlock (__objc_runtime_mutex);
return (*(node_ptr*)enum_state)->value;
return (Class)0; return class;
} }
/* 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 to
to the right meta class objects */ the right meta class objects. */
void __objc_resolve_class_links() void
__objc_resolve_class_links (void)
{ {
node_ptr node; struct class_table_enumerator *es = NULL;
Class object_class = objc_get_class ("Object"); Class object_class = objc_get_class ("Object");
Class class1;
assert(object_class); assert (object_class);
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
/* Assign subclass links */ /* Assign subclass links. */
for (node = hash_next (__objc_class_hash, NULL); node; while ((class1 = class_table_next (&es)))
node = hash_next (__objc_class_hash, node))
{ {
Class class1 = node->value;
/* Make sure we have what we think we have. */ /* Make sure we have what we think we have. */
assert (CLS_ISCLASS(class1)); assert (CLS_ISCLASS (class1));
assert (CLS_ISMETA(class1->class_pointer)); assert (CLS_ISMETA (class1->class_pointer));
/* The class_pointer of all meta classes point to Object's meta class. */ /* The class_pointer of all meta classes point to Object's meta
class. */
class1->class_pointer->class_pointer = object_class->class_pointer; class1->class_pointer->class_pointer = object_class->class_pointer;
if (!(CLS_ISRESOLV(class1))) if (! CLS_ISRESOLV (class1))
{ {
CLS_SETRESOLV(class1); CLS_SETRESOLV (class1);
CLS_SETRESOLV(class1->class_pointer); CLS_SETRESOLV (class1->class_pointer);
if(class1->super_class) if (class1->super_class)
{ {
Class a_super_class Class a_super_class
= objc_get_class ((char *) class1->super_class); = objc_get_class ((char *) class1->super_class);
@ -221,11 +579,11 @@ void __objc_resolve_class_links()
DEBUG_PRINTF ("making class connections for: %s\n", DEBUG_PRINTF ("making class connections for: %s\n",
class1->name); class1->name);
/* assign subclass links for superclass */ /* Assign subclass links for superclass. */
class1->sibling_class = a_super_class->subclass_list; class1->sibling_class = a_super_class->subclass_list;
a_super_class->subclass_list = class1; a_super_class->subclass_list = class1;
/* Assign subclass links for meta class of superclass */ /* Assign subclass links for meta class of superclass. */
if (a_super_class->class_pointer) if (a_super_class->class_pointer)
{ {
class1->class_pointer->sibling_class class1->class_pointer->sibling_class
@ -234,8 +592,8 @@ void __objc_resolve_class_links()
= class1->class_pointer; = class1->class_pointer;
} }
} }
else /* a root class, make its meta object */ else /* A root class, make its meta object be a subclass of
/* be a subclass of Object */ Object. */
{ {
class1->class_pointer->sibling_class class1->class_pointer->sibling_class
= object_class->subclass_list; = object_class->subclass_list;
@ -244,22 +602,21 @@ void __objc_resolve_class_links()
} }
} }
/* Assign superclass links */ /* Assign superclass links. */
for (node = hash_next (__objc_class_hash, NULL); node; es = NULL;
node = hash_next (__objc_class_hash, node)) while ((class1 = class_table_next (&es)))
{ {
Class class1 = node->value;
Class sub_class; Class sub_class;
for (sub_class = class1->subclass_list; sub_class; for (sub_class = class1->subclass_list; sub_class;
sub_class = sub_class->sibling_class) sub_class = sub_class->sibling_class)
{ {
sub_class->super_class = class1; sub_class->super_class = class1;
if(CLS_ISCLASS(sub_class)) if (CLS_ISCLASS (sub_class))
sub_class->class_pointer->super_class = class1->class_pointer; sub_class->class_pointer->super_class = class1->class_pointer;
} }
} }
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
@ -269,13 +626,10 @@ 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; if (! CLS_ISRESOLV (impostor))
Class class1;
if (!CLS_ISRESOLV (impostor))
__objc_resolve_class_links (); __objc_resolve_class_links ();
/* preconditions */ /* Preconditions */
assert (impostor); assert (impostor);
assert (super_class); assert (super_class);
assert (impostor->super_class == super_class); assert (impostor->super_class == super_class);
@ -286,73 +640,64 @@ class_pose_as (Class impostor, Class super_class)
{ {
Class *subclass = &(super_class->subclass_list); Class *subclass = &(super_class->subclass_list);
/* 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;
if (*subclass != impostor) if (*subclass != impostor)
{ {
Class sub = *subclass; Class sub = *subclass;
/* classes */ /* Classes */
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;
/* It will happen that SUB is not a class object if it is /* It will happen that SUB is not a class object if it is
the top of the meta class hierarchy chain. (root the top of the meta class hierarchy chain (root
meta-class objects inherit their class object) If that is meta-class objects inherit their class object). If
the case... don't mess with the meta-meta class. */ that is the case... don't mess with the meta-meta
if (CLS_ISCLASS (sub)) class. */
{ if (CLS_ISCLASS (sub))
/* meta classes */ {
CLASSOF (sub)->sibling_class = /* Meta classes */
CLASSOF (impostor)->subclass_list; CLASSOF (sub)->sibling_class =
CLASSOF (sub)->super_class = CLASSOF (impostor); CLASSOF (impostor)->subclass_list;
CLASSOF (impostor)->subclass_list = CLASSOF (sub); CLASSOF (sub)->super_class = CLASSOF (impostor);
} CLASSOF (impostor)->subclass_list = CLASSOF (sub);
} }
}
*subclass = nextSub;
*subclass = nextSub;
} }
/* set subclasses of superclass to be impostor only */ /* Set subclasses of superclass to be impostor only. */
super_class->subclass_list = impostor; super_class->subclass_list = impostor;
CLASSOF (super_class)->subclass_list = CLASSOF (impostor); CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
/* 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;
} }
/* check relationship of impostor and super_class is kept. */ /* 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));
/* This is how to update the lookup table. Regardless of /* This is how to update the lookup table. Regardless of what the
what the keys of the hashtable is, change all values that are keys of the hashtable is, change all values that are superclass
superclass into impostor. */ into impostor. */
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
for (node = hash_next (__objc_class_hash, NULL); node; class_table_replace (super_class, impostor);
node = hash_next (__objc_class_hash, node))
{
class1 = (Class)node->value;
if (class1 == super_class)
{
node->value = impostor; /* change hash table value */
}
}
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
/* next, we update the dispatch tables... */ /* Next, we update the dispatch tables... */
__objc_update_dispatch_table_for_class (CLASSOF (impostor)); __objc_update_dispatch_table_for_class (CLASSOF (impostor));
__objc_update_dispatch_table_for_class (impostor); __objc_update_dispatch_table_for_class (impostor);
return impostor; return impostor;
} }

2078
configure vendored

File diff suppressed because it is too large Load Diff

@ -1,5 +1,6 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
# Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc. # Copyright (C) 1995, 1997, 1998, 1999, 2002, 2003
# Free Software Foundation, Inc.
# Contributed by Dave Love (d.love@dl.ac.uk). # Contributed by Dave Love (d.love@dl.ac.uk).
# #
#This file is part of GNU Objective C. #This file is part of GNU Objective C.
@ -23,57 +24,32 @@ AC_PREREQ(2.13)
AC_INIT(objc/objc.h) AC_INIT(objc/objc.h)
AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(config.h)
if test "${srcdir}" = "." ; then # This works around the fact that libtool configuration may change LD
if test "${with_target_subdir}" != "." ; then # for this particular configuration, but some shells, instead of
topsrcdir=${with_multisrctop}../.. # keeping the changes in LD private, export them just because LD is
else # exported.
topsrcdir=${with_multisrctop}.. ORIGINAL_LD_FOR_MULTILIBS=$LD
fi
else GLIBCPP_TOPREL_CONFIGURE
topsrcdir=${srcdir}/..
fi AC_CANONICAL_SYSTEM
dnl This is needed for a multilibbed build in the source tree so target_alias=${target_alias-$target}
dnl that install-sh and config.sub get found. AC_SUBST(target_alias)
AC_CONFIG_AUX_DIR($topsrcdir)
GLIBCPP_CONFIGURE(.)
# If the language specific compiler does not exist, but the "gcc" directory GLIBCPP_EXPORT_INSTALL_INFO
# does, we do not build anything. Note, $r is set by the top-level Makefile.
# Note that when we look for the compiler, we search both with and without
# extension to handle cross and canadian cross builds.
compiler_name=cc1obj
rm -f skip-this-dir
AC_MSG_CHECKING(if compiler $compiler_name has been built)
AC_CACHE_VAL(objc_cv_compiler_exists,
[objc_cv_compiler_exists=yes
if test -n "$r"; then
if test -d "$r"/gcc; then
if test -f "$r"/gcc/$compiler_name \
|| test -f "$r"/gcc/$compiler_name.exe; then
true
else
objc_cv_compiler_exists=no
echo "rm -f config.cache config.log multilib.out" > skip-this-dir
fi
fi
fi
])
AC_MSG_RESULT($objc_cv_compiler_exists)
if test x$objc_cv_compiler_exists = xno
then
rm -f Makefile conftest* confdefs* core
exit 0
fi
dnl Checks for programs. dnl Checks for programs.
dnl FIXME AC_PROG_CC wants CC to be able to link things, but it may # Disable shared libs by default
dnl not be able to. AC_DISABLE_SHARED
define([AC_PROG_CC_WORKS],[]) # Enable Win32 DLL on MS Windows - FIXME
AC_LIBTOOL_WIN32_DLL
# For ObjC we'll set CC to point at the built gcc, but this will get it into AC_PROG_LIBTOOL
# the makefiles
AC_PROG_CC
dnl These should be inherited in the recursive make, but ensure they are
dnl defined:
test "$AR" || AR=ar test "$AR" || AR=ar
AC_SUBST(AR) AC_SUBST(AR)
if test "$RANLIB"; then : if test "$RANLIB"; then :
@ -82,19 +58,7 @@ else
AC_PROG_RANLIB AC_PROG_RANLIB
fi fi
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_MAKE_SET
# We need AC_EXEEXT to keep automake happy in cygnus mode. However,
# at least currently, we never actually build a program, so we never
# need to use $(EXEEXT). Moreover, the test for EXEEXT normally
# fails, because we are probably configuring with a cross compiler
# which cant create executables. So we include AC_EXEEXT to keep
# automake happy, but we dont execute it, since we dont care about
# the result.
if false; then
AC_EXEEXT
fi
dnl Checks for libraries.
dnl Checks for header files. dnl Checks for header files.
# Sanity check for the cross-compilation case: # Sanity check for the cross-compilation case:
@ -121,13 +85,6 @@ fi])
GTHREAD_FLAGS=$objc_cv_gthread_flags GTHREAD_FLAGS=$objc_cv_gthread_flags
AC_SUBST(GTHREAD_FLAGS) AC_SUBST(GTHREAD_FLAGS)
# Disable shared libs by default
AC_DISABLE_SHARED
# Enable Win32 DLL on MS Windows - FIXME
AC_LIBTOOL_WIN32_DLL
# Use libtool
AC_PROG_LIBTOOL
AC_ARG_ENABLE(objc-gc, AC_ARG_ENABLE(objc-gc,
[ --enable-objc-gc enable the use of Boehm's garbage collector with [ --enable-objc-gc enable the use of Boehm's garbage collector with
the GNU Objective-C runtime.], the GNU Objective-C runtime.],
@ -142,12 +99,13 @@ AC_SUBST(OBJC_BOEHM_GC)
# We need multilib support, but only if configuring for the target. # We need multilib support, but only if configuring for the target.
AC_OUTPUT(Makefile, AC_OUTPUT(Makefile,
[test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h [test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
if test -n "$CONFIG_FILES"; then if test -n "$CONFIG_FILES"; then
if test -n "${with_target_subdir}"; then if test -n "${with_target_subdir}"; then
# FIXME: We shouldn't need to set ac_file # FIXME: We shouldn't need to set ac_file
ac_file=Makefile ac_file=Makefile
. ${topsrcdir}/config-ml.in LD="${ORIGINAL_LD_FOR_MULTILIBS}"
. ${toplevel_srcdir}/config-ml.in
fi fi
fi], fi],
srcdir=${srcdir} srcdir=${srcdir}
@ -156,10 +114,12 @@ target=${target}
with_target_subdir=${with_target_subdir} with_target_subdir=${with_target_subdir}
with_multisubdir=${with_multisubdir} with_multisubdir=${with_multisubdir}
ac_configure_args="--enable-multilib ${ac_configure_args}" ac_configure_args="--enable-multilib ${ac_configure_args}"
toplevel_srcdir=${toplevel_srcdir}
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
topsrcdir=${topsrcdir} ORIGINAL_LD_FOR_MULTILIBS="${ORIGINAL_LD_FOR_MULTILIBS}"
) )
dnl Local Variables: dnl Local Variables:
dnl comment-start: "dnl " dnl comment-start: "dnl "
dnl comment-end: "" dnl comment-end: ""

@ -1,5 +1,6 @@
/* Encoding of types for Objective C. /* Encoding of types for Objective C.
Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2002
Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup Contributed by Kresten Krab Thorup
Bitfield support by Ovidiu Predescu Bitfield support by Ovidiu Predescu
@ -26,21 +27,29 @@ Boston, MA 02111-1307, USA. */
This exception does not however invalidate any other reasons why This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */ the executable file might be covered by the GNU General Public License. */
/* FIXME: This file has no business including tm.h. */
#include "tconfig.h" #include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
#include "objc-api.h" #include "objc-api.h"
#include "encoding.h" #include "encoding.h"
#include <stdlib.h>
#undef MAX
#define MAX(X, Y) \ #define MAX(X, Y) \
({ typeof(X) __x = (X), __y = (Y); \ ({ typeof (X) __x = (X), __y = (Y); \
(__x > __y ? __x : __y); }) (__x > __y ? __x : __y); })
#undef MIN
#define MIN(X, Y) \ #define MIN(X, Y) \
({ typeof(X) __x = (X), __y = (Y); \ ({ typeof (X) __x = (X), __y = (Y); \
(__x < __y ? __x : __y); }) (__x < __y ? __x : __y); })
#undef ROUND
#define ROUND(V, A) \ #define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \ ({ typeof (V) __v = (V); typeof (A) __a = (A); \
__a*((__v+__a-1)/__a); }) __a * ((__v+__a - 1)/__a); })
/* Various hacks for objc_layout_record. These are used by the target /* Various hacks for objc_layout_record. These are used by the target
@ -54,6 +63,10 @@ Boston, MA 02111-1307, USA. */
#define QUAL_UNION_TYPE _C_UNION_B #define QUAL_UNION_TYPE _C_UNION_B
#define ARRAY_TYPE _C_ARY_B #define ARRAY_TYPE _C_ARY_B
#define REAL_TYPE _C_DBL
#define VECTOR_TYPE _C_VECTOR
#define TYPE_FIELDS(TYPE) objc_skip_typespec (TYPE) #define TYPE_FIELDS(TYPE) objc_skip_typespec (TYPE)
#define DECL_MODE(TYPE) *(TYPE) #define DECL_MODE(TYPE) *(TYPE)
@ -69,23 +82,18 @@ Boston, MA 02111-1307, USA. */
#undef STRUCTURE_SIZE_BOUNDARY #undef STRUCTURE_SIZE_BOUNDARY
#define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;})) #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
static inline int /* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
atoi (const char* str) target_flags. Define a dummy entry here to so we don't die. */
{ /* ??? FIXME: As of 2002-06-21, the attribute `unused' doesn't seem to
int res = 0; eliminate the warning. */
static int __attribute__ ((__unused__)) target_flags = 0;
while (isdigit (*str))
res *= 10, res += (*str++ - '0');
return res;
}
/* /*
return the size of an object specified by type return the size of an object specified by type
*/ */
int int
objc_sizeof_type (const char* type) objc_sizeof_type (const char *type)
{ {
/* Skip the variable name if any */ /* Skip the variable name if any */
if (*type == '"') if (*type == '"')
@ -94,83 +102,85 @@ objc_sizeof_type (const char* type)
/* do nothing */; /* do nothing */;
} }
switch(*type) { switch (*type) {
case _C_ID: case _C_ID:
return sizeof(id); return sizeof (id);
break; break;
case _C_CLASS: case _C_CLASS:
return sizeof(Class); return sizeof (Class);
break; break;
case _C_SEL: case _C_SEL:
return sizeof(SEL); return sizeof (SEL);
break; break;
case _C_CHR: case _C_CHR:
return sizeof(char); return sizeof (char);
break; break;
case _C_UCHR: case _C_UCHR:
return sizeof(unsigned char); return sizeof (unsigned char);
break; break;
case _C_SHT: case _C_SHT:
return sizeof(short); return sizeof (short);
break; break;
case _C_USHT: case _C_USHT:
return sizeof(unsigned short); return sizeof (unsigned short);
break; break;
case _C_INT: case _C_INT:
return sizeof(int); return sizeof (int);
break; break;
case _C_UINT: case _C_UINT:
return sizeof(unsigned int); return sizeof (unsigned int);
break; break;
case _C_LNG: case _C_LNG:
return sizeof(long); return sizeof (long);
break; break;
case _C_ULNG: case _C_ULNG:
return sizeof(unsigned long); return sizeof (unsigned long);
break; break;
case _C_LNG_LNG: case _C_LNG_LNG:
return sizeof(long long); return sizeof (long long);
break; break;
case _C_ULNG_LNG: case _C_ULNG_LNG:
return sizeof(unsigned long long); return sizeof (unsigned long long);
break; break;
case _C_FLT: case _C_FLT:
return sizeof(float); return sizeof (float);
break; break;
case _C_DBL: case _C_DBL:
return sizeof(double); return sizeof (double);
break; break;
case _C_VOID: case _C_VOID:
return sizeof(void); return sizeof (void);
break; break;
case _C_PTR: case _C_PTR:
case _C_ATOM: case _C_ATOM:
case _C_CHARPTR: case _C_CHARPTR:
return sizeof(char*); return sizeof (char *);
break; break;
case _C_ARY_B: case _C_ARY_B:
{ {
int len = atoi(type+1); int len = atoi (type + 1);
while (isdigit(*++type)); while (isdigit ((unsigned char)*++type))
return len*objc_aligned_size (type); ;
return len * objc_aligned_size (type);
} }
break; break;
case _C_BFLD: case _C_BFLD:
{ {
@ -179,7 +189,8 @@ objc_sizeof_type (const char* type)
int startByte, endByte; int startByte, endByte;
position = atoi (type + 1); position = atoi (type + 1);
while (isdigit (*++type)); while (isdigit ((unsigned char)*++type))
;
size = atoi (type + 1); size = atoi (type + 1);
startByte = position / BITS_PER_UNIT; startByte = position / BITS_PER_UNIT;
@ -203,7 +214,8 @@ objc_sizeof_type (const char* type)
case _C_UNION_B: case _C_UNION_B:
{ {
int max_size = 0; int max_size = 0;
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; while (*type != _C_UNION_E && *type++ != '=')
/* do nothing */;
while (*type != _C_UNION_E) while (*type != _C_UNION_E)
{ {
/* Skip the variable name if any */ /* Skip the variable name if any */
@ -217,10 +229,10 @@ objc_sizeof_type (const char* type)
} }
return max_size; return max_size;
} }
default: default:
{ {
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type); objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0; return 0;
} }
} }
@ -228,11 +240,11 @@ objc_sizeof_type (const char* type)
/* /*
Return the alignment of an object specified by type Return the alignment of an object specified by type
*/ */
int int
objc_alignof_type(const char* type) objc_alignof_type (const char *type)
{ {
/* Skip the variable name if any */ /* Skip the variable name if any */
if (*type == '"') if (*type == '"')
@ -240,75 +252,76 @@ objc_alignof_type(const char* type)
for (type++; *type++ != '"';) for (type++; *type++ != '"';)
/* do nothing */; /* do nothing */;
} }
switch(*type) { switch (*type) {
case _C_ID: case _C_ID:
return __alignof__(id); return __alignof__ (id);
break; break;
case _C_CLASS: case _C_CLASS:
return __alignof__(Class); return __alignof__ (Class);
break; break;
case _C_SEL: case _C_SEL:
return __alignof__(SEL); return __alignof__ (SEL);
break; break;
case _C_CHR: case _C_CHR:
return __alignof__(char); return __alignof__ (char);
break; break;
case _C_UCHR: case _C_UCHR:
return __alignof__(unsigned char); return __alignof__ (unsigned char);
break; break;
case _C_SHT: case _C_SHT:
return __alignof__(short); return __alignof__ (short);
break; break;
case _C_USHT: case _C_USHT:
return __alignof__(unsigned short); return __alignof__ (unsigned short);
break; break;
case _C_INT: case _C_INT:
return __alignof__(int); return __alignof__ (int);
break; break;
case _C_UINT: case _C_UINT:
return __alignof__(unsigned int); return __alignof__ (unsigned int);
break; break;
case _C_LNG: case _C_LNG:
return __alignof__(long); return __alignof__ (long);
break; break;
case _C_ULNG: case _C_ULNG:
return __alignof__(unsigned long); return __alignof__ (unsigned long);
break; break;
case _C_LNG_LNG: case _C_LNG_LNG:
return __alignof__(long long); return __alignof__ (long long);
break; break;
case _C_ULNG_LNG: case _C_ULNG_LNG:
return __alignof__(unsigned long long); return __alignof__ (unsigned long long);
break; break;
case _C_FLT: case _C_FLT:
return __alignof__(float); return __alignof__ (float);
break; break;
case _C_DBL: case _C_DBL:
return __alignof__(double); return __alignof__ (double);
break; break;
case _C_PTR: case _C_PTR:
case _C_ATOM: case _C_ATOM:
case _C_CHARPTR: case _C_CHARPTR:
return __alignof__(char*); return __alignof__ (char *);
break; break;
case _C_ARY_B: case _C_ARY_B:
while (isdigit(*++type)) /* do nothing */; while (isdigit ((unsigned char)*++type))
/* do nothing */;
return objc_alignof_type (type); return objc_alignof_type (type);
case _C_STRUCT_B: case _C_STRUCT_B:
@ -327,7 +340,8 @@ objc_alignof_type(const char* type)
case _C_UNION_B: case _C_UNION_B:
{ {
int maxalign = 0; int maxalign = 0;
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; while (*type != _C_UNION_E && *type++ != '=')
/* do nothing */;
while (*type != _C_UNION_E) while (*type != _C_UNION_E)
{ {
/* Skip the variable name if any */ /* Skip the variable name if any */
@ -344,7 +358,7 @@ objc_alignof_type(const char* type)
default: default:
{ {
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type); objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0; return 0;
} }
} }
@ -355,7 +369,7 @@ objc_alignof_type(const char* type)
*/ */
int int
objc_aligned_size (const char* type) objc_aligned_size (const char *type)
{ {
int size, align; int size, align;
@ -374,11 +388,11 @@ objc_aligned_size (const char* type)
/* /*
The size rounded up to the nearest integral of the wordsize, taken The size rounded up to the nearest integral of the wordsize, taken
to be the size of a void*. to be the size of a void *.
*/ */
int int
objc_promoted_size (const char* type) objc_promoted_size (const char *type)
{ {
int size, wordsize; int size, wordsize;
@ -390,7 +404,7 @@ objc_promoted_size (const char* type)
} }
size = objc_sizeof_type (type); size = objc_sizeof_type (type);
wordsize = sizeof (void*); wordsize = sizeof (void *);
return ROUND (size, wordsize); return ROUND (size, wordsize);
} }
@ -400,13 +414,13 @@ objc_promoted_size (const char* type)
occurring in method prototype encodings. occurring in method prototype encodings.
*/ */
inline const char* inline const char *
objc_skip_type_qualifiers (const char* type) objc_skip_type_qualifiers (const char *type)
{ {
while (*type == _C_CONST while (*type == _C_CONST
|| *type == _C_IN || *type == _C_IN
|| *type == _C_INOUT || *type == _C_INOUT
|| *type == _C_OUT || *type == _C_OUT
|| *type == _C_BYCOPY || *type == _C_BYCOPY
|| *type == _C_BYREF || *type == _C_BYREF
|| *type == _C_ONEWAY || *type == _C_ONEWAY
@ -417,14 +431,14 @@ objc_skip_type_qualifiers (const char* type)
return type; return type;
} }
/* /*
Skip one typespec element. If the typespec is prepended by type Skip one typespec element. If the typespec is prepended by type
qualifiers, these are skipped as well. qualifiers, these are skipped as well.
*/ */
const char* const char *
objc_skip_typespec (const char* type) objc_skip_typespec (const char *type)
{ {
/* Skip the variable name if any */ /* Skip the variable name if any */
if (*type == '"') if (*type == '"')
@ -434,7 +448,7 @@ objc_skip_typespec (const char* type)
} }
type = objc_skip_type_qualifiers (type); type = objc_skip_type_qualifiers (type);
switch (*type) { switch (*type) {
case _C_ID: case _C_ID:
@ -445,7 +459,8 @@ objc_skip_typespec (const char* type)
return type; return type;
else else
{ {
while (*++type != '"') /* do nothing */; while (*++type != '"')
/* do nothing */;
return type + 1; return type + 1;
} }
@ -473,45 +488,56 @@ objc_skip_typespec (const char* type)
case _C_ARY_B: case _C_ARY_B:
/* skip digits, typespec and closing ']' */ /* skip digits, typespec and closing ']' */
while(isdigit(*++type)); while (isdigit ((unsigned char)*++type))
type = objc_skip_typespec(type); ;
type = objc_skip_typespec (type);
if (*type == _C_ARY_E) if (*type == _C_ARY_E)
return ++type; return ++type;
else else
{ {
objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type); objc_error (nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
return 0; return 0;
} }
case _C_BFLD: case _C_BFLD:
/* The new encoding of bitfields is: b 'position' 'type' 'size' */ /* The new encoding of bitfields is: b 'position' 'type' 'size' */
while (isdigit (*++type)); /* skip position */ while (isdigit ((unsigned char)*++type))
while (isdigit (*++type)); /* skip type and size */ ; /* skip position */
while (isdigit ((unsigned char)*++type))
; /* skip type and size */
return type; return type;
case _C_STRUCT_B: case _C_STRUCT_B:
/* skip name, and elements until closing '}' */ /* skip name, and elements until closing '}' */
while (*type != _C_STRUCT_E && *type++ != '='); while (*type != _C_STRUCT_E && *type++ != '=')
while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); } ;
while (*type != _C_STRUCT_E)
{
type = objc_skip_typespec (type);
}
return ++type; return ++type;
case _C_UNION_B: case _C_UNION_B:
/* skip name, and elements until closing ')' */ /* skip name, and elements until closing ')' */
while (*type != _C_UNION_E && *type++ != '='); while (*type != _C_UNION_E && *type++ != '=')
while (*type != _C_UNION_E) { type = objc_skip_typespec (type); } ;
while (*type != _C_UNION_E)
{
type = objc_skip_typespec (type);
}
return ++type; return ++type;
case _C_PTR: case _C_PTR:
/* Just skip the following typespec */ /* Just skip the following typespec */
return objc_skip_typespec (++type); return objc_skip_typespec (++type);
default: default:
{ {
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type); objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0; return 0;
} }
} }
@ -521,19 +547,21 @@ objc_skip_typespec (const char* type)
Skip an offset as part of a method encoding. This is prepended by a Skip an offset as part of a method encoding. This is prepended by a
'+' if the argument is passed in registers. '+' if the argument is passed in registers.
*/ */
inline const char* inline const char *
objc_skip_offset (const char* type) objc_skip_offset (const char *type)
{ {
if (*type == '+') type++; if (*type == '+')
while(isdigit(*++type)); type++;
while (isdigit ((unsigned char) *++type))
;
return type; return type;
} }
/* /*
Skip an argument specification of a method encoding. Skip an argument specification of a method encoding.
*/ */
const char* const char *
objc_skip_argspec (const char* type) objc_skip_argspec (const char *type)
{ {
type = objc_skip_typespec (type); type = objc_skip_typespec (type);
type = objc_skip_offset (type); type = objc_skip_offset (type);
@ -543,13 +571,13 @@ objc_skip_argspec (const char* type)
/* /*
Return the number of arguments that the method MTH expects. Return the number of arguments that the method MTH expects.
Note that all methods need two implicit arguments `self' and Note that all methods need two implicit arguments `self' and
`_cmd'. `_cmd'.
*/ */
int int
method_get_number_of_arguments (struct objc_method* mth) method_get_number_of_arguments (struct objc_method *mth)
{ {
int i = 0; int i = 0;
const char* type = mth->method_types; const char *type = mth->method_types;
while (*type) while (*type)
{ {
type = objc_skip_argspec (type); type = objc_skip_argspec (type);
@ -565,9 +593,9 @@ method_get_number_of_arguments (struct objc_method* mth)
*/ */
int int
method_get_sizeof_arguments (struct objc_method* mth) method_get_sizeof_arguments (struct objc_method *mth)
{ {
const char* type = objc_skip_typespec (mth->method_types); const char *type = objc_skip_typespec (mth->method_types);
return atoi (type); return atoi (type);
} }
@ -576,7 +604,7 @@ method_get_sizeof_arguments (struct objc_method* mth)
the last argument. Typical use of this look like: the last argument. Typical use of this look like:
{ {
char *datum, *type; char *datum, *type;
for (datum = method_get_first_argument (method, argframe, &type); for (datum = method_get_first_argument (method, argframe, &type);
datum; datum = method_get_next_argument (argframe, &type)) datum; datum = method_get_next_argument (argframe, &type))
{ {
@ -587,15 +615,14 @@ method_get_sizeof_arguments (struct objc_method* mth)
else else
{ {
if ((flags & _F_IN) == _F_IN) if ((flags & _F_IN) == _F_IN)
[portal encodeData: *(char**)datum ofType: ++type]; [portal encodeData: *(char **) datum ofType: ++type];
} }
} }
} }
*/ */
char* char *
method_get_next_argument (arglist_t argframe, method_get_next_argument (arglist_t argframe, const char **type)
const char **type)
{ {
const char *t = objc_skip_argspec (*type); const char *t = objc_skip_argspec (*type);
@ -612,15 +639,15 @@ method_get_next_argument (arglist_t argframe,
} }
/* /*
Return a pointer to the value of the first argument of the method Return a pointer to the value of the first argument of the method
described in M with the given argumentframe ARGFRAME. The type described in M with the given argumentframe ARGFRAME. The type
is returned in TYPE. type must be passed to successive calls of is returned in TYPE. type must be passed to successive calls of
method_get_next_argument. method_get_next_argument.
*/ */
char* char *
method_get_first_argument (struct objc_method* m, method_get_first_argument (struct objc_method *m,
arglist_t argframe, arglist_t argframe,
const char** type) const char **type)
{ {
*type = m->method_types; *type = m->method_types;
return method_get_next_argument (argframe, type); return method_get_next_argument (argframe, type);
@ -629,22 +656,22 @@ method_get_first_argument (struct objc_method* m,
/* /*
Return a pointer to the ARGth argument of the method Return a pointer to the ARGth argument of the method
M from the frame ARGFRAME. The type of the argument M from the frame ARGFRAME. The type of the argument
is returned in the value-result argument TYPE is returned in the value-result argument TYPE
*/ */
char* char *
method_get_nth_argument (struct objc_method* m, method_get_nth_argument (struct objc_method *m,
arglist_t argframe, int arg, arglist_t argframe, int arg,
const char **type) const char **type)
{ {
const char* t = objc_skip_argspec (m->method_types); const char *t = objc_skip_argspec (m->method_types);
if (arg > method_get_number_of_arguments (m)) if (arg > method_get_number_of_arguments (m))
return 0; return 0;
while (arg--) while (arg--)
t = objc_skip_argspec (t); t = objc_skip_argspec (t);
*type = t; *type = t;
t = objc_skip_typespec (t); t = objc_skip_typespec (t);
@ -655,7 +682,7 @@ method_get_nth_argument (struct objc_method* m,
} }
unsigned unsigned
objc_get_type_qualifiers (const char* type) objc_get_type_qualifiers (const char *type)
{ {
unsigned res = 0; unsigned res = 0;
BOOL flag = YES; BOOL flag = YES;
@ -708,7 +735,7 @@ objc_layout_structure (const char *type,
if (*type++ != _C_STRUCT_B) if (*type++ != _C_STRUCT_B)
{ {
objc_error(nil, OBJC_ERR_BAD_TYPE, objc_error (nil, OBJC_ERR_BAD_TYPE,
"record type expected in objc_layout_structure, got %s\n", "record type expected in objc_layout_structure, got %s\n",
type); type);
} }
@ -737,12 +764,11 @@ objc_layout_structure (const char *type,
BOOL BOOL
objc_layout_structure_next_member (struct objc_struct_layout *layout) objc_layout_structure_next_member (struct objc_struct_layout *layout)
{ {
register int known_align = layout->record_size;
register int desired_align = 0; register int desired_align = 0;
/* The following are used only if the field is a bitfield */ /* The following are used only if the field is a bitfield */
register const char *bfld_type; register const char *bfld_type = 0;
register int bfld_type_size, bfld_type_align, bfld_field_size; register int bfld_type_size, bfld_type_align = 0, bfld_field_size = 0;
/* The current type without the type qualifiers */ /* The current type without the type qualifiers */
const char *type; const char *type;
@ -757,7 +783,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
else { else {
/* Get the bitfield's type */ /* Get the bitfield's type */
for (bfld_type = type + 1; for (bfld_type = type + 1;
isdigit(*bfld_type); isdigit ((unsigned char)*bfld_type);
bfld_type++) bfld_type++)
/* do nothing */; /* do nothing */;
@ -781,12 +807,14 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
type = objc_skip_type_qualifiers (layout->type); type = objc_skip_type_qualifiers (layout->type);
if (*type != _C_BFLD) if (*type != _C_BFLD)
desired_align = objc_alignof_type(type) * BITS_PER_UNIT; desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
else else
{ {
desired_align = 1; desired_align = 1;
/* Skip the bitfield's offset */ /* Skip the bitfield's offset */
for (bfld_type = type + 1; isdigit(*bfld_type); bfld_type++) for (bfld_type = type + 1;
isdigit ((unsigned char) *bfld_type);
bfld_type++)
/* do nothing */; /* do nothing */;
bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT; bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
@ -806,7 +834,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
is meaningless. */ is meaningless. */
#ifndef PCC_BITFIELD_TYPE_MATTERS #ifndef PCC_BITFIELD_TYPE_MATTERS
layout->record_align = MAX (layout->record_align, desired_align); layout->record_align = MAX (layout->record_align, desired_align);
#else #else /* PCC_BITFIELD_TYPE_MATTERS */
if (*type == _C_BFLD) if (*type == _C_BFLD)
{ {
/* For these machines, a zero-length field does not /* For these machines, a zero-length field does not
@ -838,7 +866,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
} }
else else
layout->record_align = MAX (layout->record_align, desired_align); layout->record_align = MAX (layout->record_align, desired_align);
#endif #endif /* PCC_BITFIELD_TYPE_MATTERS */
/* Does this field automatically have alignment it needs /* Does this field automatically have alignment it needs
by virtue of the fields that precede it and the record's by virtue of the fields that precede it and the record's
@ -852,7 +880,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
Bump the cumulative size to multiple of field alignment. */ Bump the cumulative size to multiple of field alignment. */
layout->record_size = ROUND (layout->record_size, desired_align); layout->record_size = ROUND (layout->record_size, desired_align);
} }
/* Jump to the next field in record. */ /* Jump to the next field in record. */
layout->prev_type = layout->type; layout->prev_type = layout->type;
@ -872,7 +900,7 @@ void objc_layout_finish_structure (struct objc_struct_layout *layout,
in the record type. Round it up to a multiple of the record's in the record type. Round it up to a multiple of the record's
alignment. */ alignment. */
#if defined(ROUND_TYPE_ALIGN) && !defined(__sparc__) #if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__)
layout->record_align = ROUND_TYPE_ALIGN (layout->original_type, layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
1, 1,
layout->record_align); layout->record_align);

73
gc.c

@ -1,5 +1,5 @@
/* Basic data types for Objective C. /* Basic data types for Objective C.
Copyright (C) 1998 Free Software Foundation, Inc. Copyright (C) 1998, 2002 Free Software Foundation, Inc.
Contributed by Ovidiu Predescu. Contributed by Ovidiu Predescu.
This file is part of GNU CC. This file is part of GNU CC.
@ -58,11 +58,11 @@ typedef GC_signed_word signed_word;
The offset is incremented with the size of the type. */ The offset is incremented with the size of the type. */
#define ROUND(V, A) \ #define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \ ({ typeof (V) __v = (V); typeof (A) __a = (A); \
__a*((__v+__a-1)/__a); }) __a * ((__v+__a - 1)/__a); })
#define SET_BIT_FOR_OFFSET(mask, offset) \ #define SET_BIT_FOR_OFFSET(mask, offset) \
GC_set_bit(mask, offset / sizeof (void*)) GC_set_bit (mask, offset / sizeof (void *))
/* Some prototypes */ /* Some prototypes */
static void static void
@ -74,9 +74,9 @@ __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
static void static void
__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset) __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
{ {
int i, len = atoi(type + 1); int i, len = atoi (type + 1);
while (isdigit(*++type)) while (isdigit (*++type))
/* do nothing */; /* skip the size of the array */ /* do nothing */; /* skip the size of the array */
switch (*type) { switch (*type) {
@ -138,8 +138,8 @@ __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
case _C_PTR: case _C_PTR:
case _C_CHARPTR: case _C_CHARPTR:
case _C_ATOM: case _C_ATOM:
if (!gc_invisible) if (! gc_invisible)
SET_BIT_FOR_OFFSET(mask, position); SET_BIT_FOR_OFFSET (mask, position);
break; break;
case _C_ARY_B: case _C_ARY_B:
@ -178,11 +178,11 @@ __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
size = objc_sizeof_type (type); size = objc_sizeof_type (type);
align = objc_alignof_type (type); align = objc_alignof_type (type);
offset = ROUND(offset, align); offset = ROUND (offset, align);
for (i = 0; i < size; i += sizeof (void*)) for (i = 0; i < size; i += sizeof (void *))
{ {
SET_BIT_FOR_OFFSET(mask, offset); SET_BIT_FOR_OFFSET (mask, offset);
offset += sizeof (void*); offset += sizeof (void *);
} }
} }
@ -223,8 +223,8 @@ __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
case _C_SEL: case _C_SEL:
case _C_PTR: case _C_PTR:
case _C_CHARPTR: case _C_CHARPTR:
if (!gc_invisible) if (! gc_invisible)
SET_BIT_FOR_OFFSET(mask, offset); SET_BIT_FOR_OFFSET (mask, offset);
break; break;
case _C_ARY_B: case _C_ARY_B:
@ -254,9 +254,9 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
int *current) int *current)
{ {
int i, ivar_count; int i, ivar_count;
struct objc_ivar_list* ivars; struct objc_ivar_list *ivars;
if (!class) if (! class)
{ {
strcat (*type, "{"); strcat (*type, "{");
*current++; *current++;
@ -267,7 +267,7 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
__objc_class_structure_encoding (class->super_class, type, size, current); __objc_class_structure_encoding (class->super_class, type, size, current);
ivars = class->ivars; ivars = class->ivars;
if (!ivars) if (! ivars)
return; return;
ivar_count = ivars->ivar_count; ivar_count = ivars->ivar_count;
@ -282,7 +282,7 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
{ {
/* Increase the size of the encoding string so that it /* Increase the size of the encoding string so that it
contains this ivar's type. */ contains this ivar's type. */
*size = ROUND(*current + len + 1, 10); *size = ROUND (*current + len + 1, 10);
*type = objc_realloc (*type, *size); *type = objc_realloc (*type, *size);
} }
strcat (*type + *current, ivar_type); strcat (*type + *current, ivar_type);
@ -302,7 +302,7 @@ __objc_generate_gc_type_description (Class class)
int type_size = 10, current; int type_size = 10, current;
char *class_structure_type; char *class_structure_type;
if (!CLS_ISCLASS(class)) if (! CLS_ISCLASS (class))
return; return;
/* We have to create a mask in which each bit counts for a pointer member. /* We have to create a mask in which each bit counts for a pointer member.
@ -311,9 +311,9 @@ __objc_generate_gc_type_description (Class class)
/* The number of bits in the mask is the size of an instance in bytes divided /* The number of bits in the mask is the size of an instance in bytes divided
by the size of a pointer. */ by the size of a pointer. */
bits_no = (ROUND(class_get_instance_size (class), sizeof(void*)) bits_no = (ROUND (class_get_instance_size (class), sizeof (void *))
/ sizeof (void*)); / sizeof (void *));
size = ROUND(bits_no, BITS_PER_WORD) / BITS_PER_WORD; size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
mask = objc_atomic_malloc (size * sizeof (int)); mask = objc_atomic_malloc (size * sizeof (int));
memset (mask, 0, size * sizeof (int)); memset (mask, 0, size * sizeof (int));
@ -324,12 +324,13 @@ __objc_generate_gc_type_description (Class class)
if (current + 1 == type_size) if (current + 1 == type_size)
class_structure_type = objc_realloc (class_structure_type, ++type_size); class_structure_type = objc_realloc (class_structure_type, ++type_size);
strcat (class_structure_type + current, "}"); strcat (class_structure_type + current, "}");
// printf ("type description for '%s' is %s\n", class->name, class_structure_type); #ifdef DEBUG
printf ("type description for '%s' is %s\n", class->name, class_structure_type);
#endif
__objc_gc_type_description_from_type (mask, class_structure_type); __objc_gc_type_description_from_type (mask, class_structure_type);
objc_free (class_structure_type); objc_free (class_structure_type);
#define DEBUG 1
#ifdef DEBUG #ifdef DEBUG
printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:", printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
class_structure_type, class->name, bits_no, size); class_structure_type, class->name, bits_no, size);
@ -341,7 +342,7 @@ __objc_generate_gc_type_description (Class class)
puts (""); puts ("");
#endif #endif
class->gc_object_type = (void*)GC_make_descriptor (mask, bits_no); class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
} }
@ -369,17 +370,17 @@ __objc_ivar_pointer (const char *type)
This operation only makes sense on instance variables that are This operation only makes sense on instance variables that are
pointers. */ pointers. */
void void
class_ivar_set_gcinvisible (Class class, const char* ivarname, class_ivar_set_gcinvisible (Class class, const char *ivarname,
BOOL gc_invisible) BOOL gc_invisible)
{ {
int i, ivar_count; int i, ivar_count;
struct objc_ivar_list* ivars; struct objc_ivar_list *ivars;
if (!class || !ivarname) if (! class || ! ivarname)
return; return;
ivars = class->ivars; ivars = class->ivars;
if (!ivars) if (! ivars)
return; return;
ivar_count = ivars->ivar_count; ivar_count = ivars->ivar_count;
@ -389,7 +390,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
struct objc_ivar *ivar = &(ivars->ivar_list[i]); struct objc_ivar *ivar = &(ivars->ivar_list[i]);
const char *type; const char *type;
if (!ivar->ivar_name || strcmp (ivar->ivar_name, ivarname)) if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
continue; continue;
assert (ivar->ivar_type); assert (ivar->ivar_type);
@ -406,7 +407,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
{ {
char *new_type; char *new_type;
if (gc_invisible || !__objc_ivar_pointer (type)) if (gc_invisible || ! __objc_ivar_pointer (type))
return; /* The type of the variable already matches the return; /* The type of the variable already matches the
requested gc_invisible type */ requested gc_invisible type */
@ -421,7 +422,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
{ {
char *new_type; char *new_type;
if (!gc_invisible || !__objc_ivar_pointer (type)) if (! gc_invisible || ! __objc_ivar_pointer (type))
return; /* The type of the variable already matches the return; /* The type of the variable already matches the
requested gc_invisible type */ requested gc_invisible type */
@ -445,13 +446,13 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
#else /* !OBJC_WITH_GC */ #else /* !OBJC_WITH_GC */
void void
__objc_generate_gc_type_description (Class class) __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
{ {
} }
void class_ivar_set_gcinvisible (Class class, void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
const char* ivarname, const char *ivarname __attribute__ ((__unused__)),
BOOL gc_invisible) BOOL gc_invisible __attribute__ ((__unused__)))
{ {
} }

103
misc.c

@ -1,5 +1,6 @@
/* GNU Objective C Runtime Miscellaneous /* GNU Objective C Runtime Miscellaneous
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. Copyright (C) 1993, 1994, 1995, 1996, 1997, 2002
Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup Contributed by Kresten Krab Thorup
This file is part of GNU CC. This file is part of GNU CC.
@ -37,25 +38,25 @@ static objc_error_handler _objc_error_handler = NULL;
/* Trigger an objc error */ /* Trigger an objc error */
void void
objc_error(id object, int code, const char* fmt, ...) objc_error (id object, int code, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start (ap, fmt);
objc_verror(object, code, fmt, ap); objc_verror (object, code, fmt, ap);
va_end(ap); va_end (ap);
} }
/* Trigger an objc error */ /* Trigger an objc error */
void void
objc_verror(id object, int code, const char* fmt, va_list ap) objc_verror (id object, int code, const char *fmt, va_list ap)
{ {
BOOL result = NO; BOOL result = NO;
/* Call the error handler if its there /* Call the error handler if its there
Otherwise print to stderr */ Otherwise print to stderr */
if (_objc_error_handler) if (_objc_error_handler)
result = (*_objc_error_handler)(object, code, fmt, ap); result = (*_objc_error_handler) (object, code, fmt, ap);
else else
vfprintf (stderr, fmt, ap); vfprintf (stderr, fmt, ap);
@ -64,12 +65,12 @@ objc_verror(id object, int code, const char* fmt, va_list ap)
if (result) if (result)
return; return;
else else
abort(); abort ();
} }
/* Set the error handler */ /* Set the error handler */
objc_error_handler objc_error_handler
objc_set_error_handler(objc_error_handler func) objc_set_error_handler (objc_error_handler func)
{ {
objc_error_handler temp = _objc_error_handler; objc_error_handler temp = _objc_error_handler;
_objc_error_handler = func; _objc_error_handler = func;
@ -84,54 +85,54 @@ objc_set_error_handler(objc_error_handler func)
*/ */
void * void *
objc_malloc(size_t size) objc_malloc (size_t size)
{ {
void* res = (void*) (*_objc_malloc)(size); void *res = (void *) (*_objc_malloc) (size);
if(!res) if (! res)
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res; return res;
} }
void * void *
objc_atomic_malloc(size_t size) objc_atomic_malloc (size_t size)
{ {
void* res = (void*) (*_objc_atomic_malloc)(size); void *res = (void *) (*_objc_atomic_malloc) (size);
if(!res) if (! res)
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res; return res;
} }
void * void *
objc_valloc(size_t size) objc_valloc (size_t size)
{ {
void* res = (void*) (*_objc_valloc)(size); void *res = (void *) (*_objc_valloc) (size);
if(!res) if (! res)
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res; return res;
} }
void * void *
objc_realloc(void *mem, size_t size) objc_realloc (void *mem, size_t size)
{ {
void* res = (void*) (*_objc_realloc)(mem, size); void *res = (void *) (*_objc_realloc) (mem, size);
if(!res) if (! res)
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res; return res;
} }
void * void *
objc_calloc(size_t nelem, size_t size) objc_calloc (size_t nelem, size_t size)
{ {
void* res = (void*) (*_objc_calloc)(nelem, size); void *res = (void *) (*_objc_calloc) (nelem, size);
if(!res) if (! res)
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res; return res;
} }
void void
objc_free(void *mem) objc_free (void *mem)
{ {
(*_objc_free)(mem); (*_objc_free) (mem);
} }
/* /*
@ -148,33 +149,37 @@ objc_free(void *mem)
#if OBJC_WITH_GC #if OBJC_WITH_GC
#include <gc.h> #include <gc.h>
static void *GC_calloc (size_t nelem, size_t size) static void *
GC_calloc (size_t nelem, size_t size)
{ {
void* p = GC_malloc (nelem * size); void *p = GC_malloc (nelem * size);
if (!p) if (! p)
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted!\n"); objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted!\n");
memset (p, 0, nelem * size); memset (p, 0, nelem * size);
return p; return p;
} }
static void noFree (void* p) {} static void
noFree (void *p)
{
}
void *(*_objc_malloc)(size_t) = GC_malloc; void *(*_objc_malloc) (size_t) = GC_malloc;
void *(*_objc_atomic_malloc)(size_t) = GC_malloc_atomic; void *(*_objc_atomic_malloc) (size_t) = GC_malloc_atomic;
void *(*_objc_valloc)(size_t) = GC_malloc; void *(*_objc_valloc) (size_t) = GC_malloc;
void *(*_objc_realloc)(void *, size_t) = GC_realloc; void *(*_objc_realloc) (void *, size_t) = GC_realloc;
void *(*_objc_calloc)(size_t, size_t) = GC_calloc; void *(*_objc_calloc) (size_t, size_t) = GC_calloc;
void (*_objc_free)(void *) = noFree; void (*_objc_free) (void *) = noFree;
#else #else /* !OBJC_WITH_GC */
void *(*_objc_malloc)(size_t) = malloc; void *(*_objc_malloc) (size_t) = malloc;
void *(*_objc_atomic_malloc)(size_t) = malloc; void *(*_objc_atomic_malloc) (size_t) = malloc;
void *(*_objc_valloc)(size_t) = malloc; void *(*_objc_valloc) (size_t) = malloc;
void *(*_objc_realloc)(void *, size_t) = realloc; void *(*_objc_realloc) (void *, size_t) = realloc;
void *(*_objc_calloc)(size_t, size_t) = calloc; void *(*_objc_calloc) (size_t, size_t) = calloc;
void (*_objc_free)(void *) = free; void (*_objc_free) (void *) = free;
#endif #endif /* !OBJC_WITH_GC */

@ -1,5 +1,5 @@
/* GNU Objective C Runtime nil receiver function /* GNU Objective C Runtime nil receiver function
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup Contributed by Kresten Krab Thorup
This file is part of GNU CC. This file is part of GNU CC.
@ -29,12 +29,27 @@ Boston, MA 02111-1307, USA. */
#include "runtime.h" #include "runtime.h"
/* When the receiver of a method invocation is nil, the runtime
returns nil_method() as the method implementation. This function
will be casted to whatever function was supposed to be executed to
execute that method (that function will take an id, followed by a
SEL, followed by who knows what arguments, depends on the method),
and executed.
For this reason, nil_method() should be a function which can be
called in place of any function taking an 'id' argument followed by
a 'SEL' argument, followed by zero, or one, or any number of
arguments (both a fixed number, or a variable number !).
There is no "proper" implementation of such a nil_method function
in C, however in all existing implementations it does not matter
when extra arguments are present, so we can simply create a function
taking a receiver and a selector, and all other arguments will be
ignored. :-)
*/
id id
nil_method(id receiver, SEL op, ...) nil_method (id receiver, SEL op __attribute__ ((__unused__)))
{ {
return receiver; return receiver;
} }

@ -1,5 +1,5 @@
/* Encoding of types for Objective C. /* Encoding of types for Objective C.
Copyright (C) 1993, 1997 Free Software Foundation, Inc. Copyright (C) 1993, 1997, 2002 Free Software Foundation, Inc.
Author: Kresten Krab Thorup Author: Kresten Krab Thorup
@ -50,30 +50,30 @@ Boston, MA 02111-1307, USA. */
#define _F_ONEWAY 0x10 #define _F_ONEWAY 0x10
#define _F_GCINVISIBLE 0x20 #define _F_GCINVISIBLE 0x20
int objc_aligned_size (const char* type); int objc_aligned_size (const char *type);
int objc_sizeof_type (const char* type); int objc_sizeof_type (const char *type);
int objc_alignof_type (const char* type); int objc_alignof_type (const char *type);
int objc_aligned_size (const char* type); int objc_aligned_size (const char *type);
int objc_promoted_size (const char* type); int objc_promoted_size (const char *type);
const char* objc_skip_type_qualifiers (const char* type); const char *objc_skip_type_qualifiers (const char *type);
const char* objc_skip_typespec (const char* type); const char *objc_skip_typespec (const char *type);
const char* objc_skip_offset (const char* type); const char *objc_skip_offset (const char *type);
const char* objc_skip_argspec (const char* type); const char *objc_skip_argspec (const char *type);
int method_get_number_of_arguments (struct objc_method*); int method_get_number_of_arguments (struct objc_method *);
int method_get_sizeof_arguments (struct objc_method*); int method_get_sizeof_arguments (struct objc_method *);
char* method_get_first_argument (struct objc_method*, char *method_get_first_argument (struct objc_method *,
arglist_t argframe, arglist_t argframe,
const char** type); const char **type);
char* method_get_next_argument (arglist_t argframe, char *method_get_next_argument (arglist_t argframe,
const char **type); const char **type);
char* method_get_nth_argument (struct objc_method* m, char *method_get_nth_argument (struct objc_method *m,
arglist_t argframe, arglist_t argframe,
int arg, int arg,
const char **type); const char **type);
unsigned objc_get_type_qualifiers (const char* type); unsigned objc_get_type_qualifiers (const char *type);
struct objc_struct_layout struct objc_struct_layout

@ -73,7 +73,14 @@ typedef struct objc_object {
/* /*
** Definition of method type. When retrieving the implementation of a ** Definition of method type. When retrieving the implementation of a
** method, this is type of the pointer returned ** method, this is type of the pointer returned. The idea of the
** definition of IMP is to represent a 'pointer to a general function
** taking an id, a SEL, followed by other unspecified arguments'. You
** must always cast an IMP to a pointer to a function taking the
** appropriate, specific types for that function, before calling it -
** to make sure the appropriate arguments are passed to it. The code
** generated by the compiler to perform method calls automatically
** does this cast inside method calls.
*/ */
typedef id (*IMP)(id, SEL, ...); typedef id (*IMP)(id, SEL, ...);

@ -1,5 +1,5 @@
/* Thread and mutex controls for Objective C. /* Thread and mutex controls for Objective C.
Copyright (C) 1996, 1997 Free Software Foundation, Inc. Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
This file is part of GNU CC. This file is part of GNU CC.
@ -74,30 +74,30 @@ struct objc_condition
typedef struct objc_condition *objc_condition_t; typedef struct objc_condition *objc_condition_t;
/* Frontend mutex functions */ /* Frontend mutex functions */
objc_mutex_t objc_mutex_allocate(void); objc_mutex_t objc_mutex_allocate (void);
int objc_mutex_deallocate(objc_mutex_t mutex); int objc_mutex_deallocate (objc_mutex_t mutex);
int objc_mutex_lock(objc_mutex_t mutex); int objc_mutex_lock (objc_mutex_t mutex);
int objc_mutex_unlock(objc_mutex_t mutex); int objc_mutex_unlock (objc_mutex_t mutex);
int objc_mutex_trylock(objc_mutex_t mutex); int objc_mutex_trylock (objc_mutex_t mutex);
/* Frontend condition mutex functions */ /* Frontend condition mutex functions */
objc_condition_t objc_condition_allocate(void); objc_condition_t objc_condition_allocate (void);
int objc_condition_deallocate(objc_condition_t condition); int objc_condition_deallocate (objc_condition_t condition);
int objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex); int objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex);
int objc_condition_signal(objc_condition_t condition); int objc_condition_signal (objc_condition_t condition);
int objc_condition_broadcast(objc_condition_t condition); int objc_condition_broadcast (objc_condition_t condition);
/* Frontend thread functions */ /* Frontend thread functions */
objc_thread_t objc_thread_detach(SEL selector, id object, id argument); objc_thread_t objc_thread_detach (SEL selector, id object, id argument);
void objc_thread_yield(void); void objc_thread_yield (void);
int objc_thread_exit(void); int objc_thread_exit (void);
int objc_thread_set_priority(int priority); int objc_thread_set_priority (int priority);
int objc_thread_get_priority(void); int objc_thread_get_priority (void);
void * objc_thread_get_data(void); void * objc_thread_get_data (void);
int objc_thread_set_data(void *value); int objc_thread_set_data (void *value);
objc_thread_t objc_thread_id(void); objc_thread_t objc_thread_id (void);
void objc_thread_add(void); void objc_thread_add (void);
void objc_thread_remove(void); void objc_thread_remove (void);
/* /*
Use this to set the hook function that will be called when the Use this to set the hook function that will be called when the
@ -111,35 +111,35 @@ void objc_thread_remove(void);
it can be informed; for example, the GNUstep Base Library sets it it can be informed; for example, the GNUstep Base Library sets it
so it can implement the NSBecomingMultiThreaded notification. so it can implement the NSBecomingMultiThreaded notification.
*/ */
typedef void (*objc_thread_callback)(); typedef void (*objc_thread_callback) (void);
objc_thread_callback objc_set_thread_callback(objc_thread_callback func); objc_thread_callback objc_set_thread_callback (objc_thread_callback func);
/* Backend initialization functions */ /* Backend initialization functions */
int __objc_init_thread_system(void); int __objc_init_thread_system (void);
int __objc_fini_thread_system(void); int __objc_fini_thread_system (void);
/* Backend mutex functions */ /* Backend mutex functions */
int __objc_mutex_allocate(objc_mutex_t mutex); int __objc_mutex_allocate (objc_mutex_t mutex);
int __objc_mutex_deallocate(objc_mutex_t mutex); int __objc_mutex_deallocate (objc_mutex_t mutex);
int __objc_mutex_lock(objc_mutex_t mutex); int __objc_mutex_lock (objc_mutex_t mutex);
int __objc_mutex_trylock(objc_mutex_t mutex); int __objc_mutex_trylock (objc_mutex_t mutex);
int __objc_mutex_unlock(objc_mutex_t mutex); int __objc_mutex_unlock (objc_mutex_t mutex);
/* Backend condition mutex functions */ /* Backend condition mutex functions */
int __objc_condition_allocate(objc_condition_t condition); int __objc_condition_allocate (objc_condition_t condition);
int __objc_condition_deallocate(objc_condition_t condition); int __objc_condition_deallocate (objc_condition_t condition);
int __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex); int __objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex);
int __objc_condition_broadcast(objc_condition_t condition); int __objc_condition_broadcast (objc_condition_t condition);
int __objc_condition_signal(objc_condition_t condition); int __objc_condition_signal (objc_condition_t condition);
/* Backend thread functions */ /* Backend thread functions */
objc_thread_t __objc_thread_detach(void (*func)(void *arg), void *arg); objc_thread_t __objc_thread_detach (void (*func) (void *arg), void *arg);
int __objc_thread_set_priority(int priority); int __objc_thread_set_priority (int priority);
int __objc_thread_get_priority(void); int __objc_thread_get_priority (void);
void __objc_thread_yield(void); void __objc_thread_yield (void);
int __objc_thread_exit(void); int __objc_thread_exit (void);
objc_thread_t __objc_thread_id(void); objc_thread_t __objc_thread_id (void);
int __objc_thread_set_data(void *value); int __objc_thread_set_data (void *value);
void * __objc_thread_get_data(void); void * __objc_thread_get_data (void);
#endif /* not __thread_INCLUDE_GNU */ #endif /* not __thread_INCLUDE_GNU */

@ -32,29 +32,29 @@ Boston, MA 02111-1307, USA. */
# include <gc.h> # include <gc.h>
#endif #endif
id __objc_object_alloc(Class); id __objc_object_alloc (Class);
id __objc_object_dispose(id); id __objc_object_dispose (id);
id __objc_object_copy(id); id __objc_object_copy (id);
id (*_objc_object_alloc)(Class) = __objc_object_alloc; /* !T:SINGLE */ id (*_objc_object_alloc) (Class) = __objc_object_alloc; /* !T:SINGLE */
id (*_objc_object_dispose)(id) = __objc_object_dispose; /* !T:SINGLE */ id (*_objc_object_dispose) (id) = __objc_object_dispose; /* !T:SINGLE */
id (*_objc_object_copy)(id) = __objc_object_copy; /* !T:SINGLE */ id (*_objc_object_copy) (id) = __objc_object_copy; /* !T:SINGLE */
id id
class_create_instance(Class class) class_create_instance (Class class)
{ {
id new = nil; id new = nil;
#if OBJC_WITH_GC #if OBJC_WITH_GC
if (CLS_ISCLASS(class)) if (CLS_ISCLASS (class))
new = (id)GC_malloc_explicitly_typed (class->instance_size, new = (id) GC_malloc_explicitly_typed (class->instance_size,
class->gc_object_type); class->gc_object_type);
#else #else
if (CLS_ISCLASS(class)) if (CLS_ISCLASS (class))
new = (*_objc_object_alloc)(class); new = (*_objc_object_alloc) (class);
#endif #endif
if (new!=nil) if (new != nil)
{ {
memset (new, 0, class->instance_size); memset (new, 0, class->instance_size);
new->class_pointer = class; new->class_pointer = class;
@ -63,43 +63,41 @@ class_create_instance(Class class)
} }
id id
object_copy(id object) object_copy (id object)
{ {
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer)) if ((object != nil) && CLS_ISCLASS (object->class_pointer))
return (*_objc_object_copy)(object); return (*_objc_object_copy) (object);
else else
return nil; return nil;
} }
id id
object_dispose(id object) object_dispose (id object)
{ {
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer)) if ((object != nil) && CLS_ISCLASS (object->class_pointer))
{ {
if (_objc_object_dispose) if (_objc_object_dispose)
(*_objc_object_dispose)(object); (*_objc_object_dispose) (object);
else else
objc_free(object); objc_free (object);
} }
return nil; return nil;
} }
id __objc_object_alloc(Class class) id __objc_object_alloc (Class class)
{ {
return (id)objc_malloc(class->instance_size); return (id) objc_malloc (class->instance_size);
} }
id __objc_object_dispose(id object) id __objc_object_dispose (id object)
{ {
objc_free(object); objc_free (object);
return 0; return 0;
} }
id __objc_object_copy(id object) id __objc_object_copy (id object)
{ {
id copy = class_create_instance(object->class_pointer); id copy = class_create_instance (object->class_pointer);
memcpy(copy, object, object->class_pointer->instance_size); memcpy (copy, object, object->class_pointer->instance_size);
return copy; return copy;
} }

@ -1,5 +1,5 @@
/* Sparse Arrays for Objective C dispatch tables /* Sparse Arrays for Objective C dispatch tables
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
@ -34,36 +34,36 @@ int nindices = 0; /* !T:MUTEX */
int narrays = 0; /* !T:MUTEX */ int narrays = 0; /* !T:MUTEX */
int idxsize = 0; /* !T:MUTEX */ int idxsize = 0; /* !T:MUTEX */
static void * first_free_data = NULL; /* !T:MUTEX */ static void *first_free_data = NULL; /* !T:MUTEX */
#ifdef OBJC_SPARSE2 #ifdef OBJC_SPARSE2
const char* __objc_sparse2_id = "2 level sparse indices"; const char *__objc_sparse2_id = "2 level sparse indices";
#endif #endif
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
const char* __objc_sparse3_id = "3 level sparse indices"; const char *__objc_sparse3_id = "3 level sparse indices";
#endif #endif
/* This function removes any structures left over from free operations /* This function removes any structures left over from free operations
that were not safe in a multi-threaded environment. */ that were not safe in a multi-threaded environment. */
void void
sarray_remove_garbage(void) sarray_remove_garbage (void)
{ {
void **vp; void **vp;
void *np; void *np;
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
vp = first_free_data; vp = first_free_data;
first_free_data = NULL; first_free_data = NULL;
while (vp) { while (vp) {
np = *vp; np = *vp;
objc_free(vp); objc_free (vp);
vp = np; vp = np;
} }
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
/* Free a block of dynamically allocated memory. If we are in multi-threaded /* Free a block of dynamically allocated memory. If we are in multi-threaded
@ -71,33 +71,33 @@ sarray_remove_garbage(void)
freed later. */ freed later. */
static void static void
sarray_free_garbage(void *vp) sarray_free_garbage (void *vp)
{ {
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
if (__objc_runtime_threads_alive == 1) { if (__objc_runtime_threads_alive == 1) {
objc_free(vp); objc_free (vp);
if (first_free_data) if (first_free_data)
sarray_remove_garbage(); sarray_remove_garbage ();
} }
else { else {
*(void **)vp = first_free_data; *(void **)vp = first_free_data;
first_free_data = vp; first_free_data = vp;
} }
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
/* sarray_at_put : copies data in such a way as to be thread reader safe. */ /* sarray_at_put : copies data in such a way as to be thread reader safe. */
void void
sarray_at_put(struct sarray* array, sidx index, void* element) sarray_at_put (struct sarray *array, sidx index, void *element)
{ {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
struct sindex** the_index; struct sindex **the_index;
struct sindex* new_index; struct sindex *new_index;
#endif #endif
struct sbucket** the_bucket; struct sbucket **the_bucket;
struct sbucket* new_bucket; struct sbucket *new_bucket;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
size_t ioffset; size_t ioffset;
#endif #endif
@ -122,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
#endif #endif
#endif /* not PRECOMPUTE_SELECTORS */ #endif /* not PRECOMPUTE_SELECTORS */
assert(soffset_decode(index) < array->capacity); /* Range check */ assert (soffset_decode (index) < array->capacity); /* Range check */
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
the_index = &(array->indices[ioffset]); the_index = &(array->indices[ioffset]);
@ -141,8 +141,8 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
if ((*the_index) == array->empty_index) { if ((*the_index) == array->empty_index) {
/* The index was previously empty, allocate a new */ /* The index was previously empty, allocate a new */
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex)); new_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
memcpy(new_index, array->empty_index, sizeof(struct sindex)); memcpy (new_index, array->empty_index, sizeof (struct sindex));
new_index->version.version = array->version.version; new_index->version.version = array->version.version;
*the_index = new_index; /* Prepared for install. */ *the_index = new_index; /* Prepared for install. */
the_bucket = &((*the_index)->buckets[boffset]); the_bucket = &((*the_index)->buckets[boffset]);
@ -151,9 +151,9 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
} else if ((*the_index)->version.version != array->version.version) { } else if ((*the_index)->version.version != array->version.version) {
/* This index must be lazy copied */ /* This index must be lazy copied */
struct sindex* old_index = *the_index; struct sindex *old_index = *the_index;
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex)); new_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
memcpy( new_index, old_index, sizeof(struct sindex)); memcpy (new_index, old_index, sizeof (struct sindex));
new_index->version.version = array->version.version; new_index->version.version = array->version.version;
*the_index = new_index; /* Prepared for install. */ *the_index = new_index; /* Prepared for install. */
the_bucket = &((*the_index)->buckets[boffset]); the_bucket = &((*the_index)->buckets[boffset]);
@ -169,9 +169,9 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
/* The bucket was previously empty (or something like that), */ /* The bucket was previously empty (or something like that), */
/* allocate a new. This is the effect of `lazy' allocation */ /* allocate a new. This is the effect of `lazy' allocation */
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket)); new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
memcpy((void *) new_bucket, (const void*)array->empty_bucket, memcpy ((void *) new_bucket, (const void *) array->empty_bucket,
sizeof(struct sbucket)); sizeof (struct sbucket));
new_bucket->version.version = array->version.version; new_bucket->version.version = array->version.version;
*the_bucket = new_bucket; /* Prepared for install. */ *the_bucket = new_bucket; /* Prepared for install. */
@ -180,9 +180,9 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
} else if ((*the_bucket)->version.version != array->version.version) { } else if ((*the_bucket)->version.version != array->version.version) {
/* Perform lazy copy. */ /* Perform lazy copy. */
struct sbucket* old_bucket = *the_bucket; struct sbucket *old_bucket = *the_bucket;
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket)); new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
memcpy( new_bucket, old_bucket, sizeof(struct sbucket)); memcpy (new_bucket, old_bucket, sizeof (struct sbucket));
new_bucket->version.version = array->version.version; new_bucket->version.version = array->version.version;
*the_bucket = new_bucket; /* Prepared for install. */ *the_bucket = new_bucket; /* Prepared for install. */
@ -193,39 +193,39 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
} }
void void
sarray_at_put_safe(struct sarray* array, sidx index, void* element) sarray_at_put_safe (struct sarray *array, sidx index, void *element)
{ {
if(soffset_decode(index) >= array->capacity) if (soffset_decode (index) >= array->capacity)
sarray_realloc(array, soffset_decode(index)+1); sarray_realloc (array, soffset_decode (index) + 1);
sarray_at_put(array, index, element); sarray_at_put (array, index, element);
} }
struct sarray* struct sarray *
sarray_new (int size, void* default_element) sarray_new (int size, void *default_element)
{ {
struct sarray* arr; struct sarray *arr;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1; size_t num_indices = ((size - 1)/(INDEX_CAPACITY)) + 1;
struct sindex ** new_indices; struct sindex **new_indices;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
size_t num_indices = ((size-1)/BUCKET_SIZE)+1; size_t num_indices = ((size - 1)/BUCKET_SIZE) + 1;
struct sbucket ** new_buckets; struct sbucket **new_buckets;
#endif #endif
int counter; size_t counter;
assert(size > 0); assert (size > 0);
/* Allocate core array */ /* Allocate core array */
arr = (struct sarray*) objc_malloc(sizeof(struct sarray)); arr = (struct sarray *) objc_malloc (sizeof (struct sarray));
arr->version.version = 0; arr->version.version = 0;
/* Initialize members */ /* Initialize members */
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
arr->capacity = num_indices*INDEX_CAPACITY; arr->capacity = num_indices*INDEX_CAPACITY;
new_indices = (struct sindex**) new_indices = (struct sindex **)
objc_malloc(sizeof(struct sindex*)*num_indices); objc_malloc (sizeof (struct sindex *) * num_indices);
arr->empty_index = (struct sindex*) objc_malloc(sizeof(struct sindex)); arr->empty_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
arr->empty_index->version.version = 0; arr->empty_index->version.version = 0;
narrays += 1; narrays += 1;
@ -234,35 +234,35 @@ sarray_new (int size, void* default_element)
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
arr->capacity = num_indices*BUCKET_SIZE; arr->capacity = num_indices*BUCKET_SIZE;
new_buckets = (struct sbucket**) new_buckets = (struct sbucket **)
objc_malloc(sizeof(struct sbucket*)*num_indices); objc_malloc (sizeof (struct sbucket *) * num_indices);
narrays += 1; narrays += 1;
idxsize += num_indices; idxsize += num_indices;
#endif #endif
arr->empty_bucket = (struct sbucket*) objc_malloc(sizeof(struct sbucket)); arr->empty_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
arr->empty_bucket->version.version = 0; arr->empty_bucket->version.version = 0;
nbuckets += 1; nbuckets += 1;
arr->ref_count = 1; arr->ref_count = 1;
arr->is_copy_of = (struct sarray*)0; arr->is_copy_of = (struct sarray *) 0;
for (counter=0; counter<BUCKET_SIZE; counter++) for (counter = 0; counter < BUCKET_SIZE; counter++)
arr->empty_bucket->elems[counter] = default_element; arr->empty_bucket->elems[counter] = default_element;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
for (counter=0; counter<INDEX_SIZE; counter++) for (counter = 0; counter < INDEX_SIZE; counter++)
arr->empty_index->buckets[counter] = arr->empty_bucket; arr->empty_index->buckets[counter] = arr->empty_bucket;
for (counter=0; counter<num_indices; counter++) for (counter = 0; counter < num_indices; counter++)
new_indices[counter] = arr->empty_index; new_indices[counter] = arr->empty_index;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
for (counter=0; counter<num_indices; counter++) for (counter = 0; counter < num_indices; counter++)
new_buckets[counter] = arr->empty_bucket; new_buckets[counter] = arr->empty_bucket;
#endif #endif
@ -282,48 +282,48 @@ sarray_new (int size, void* default_element)
any concurrent readers notice the update. */ any concurrent readers notice the update. */
void void
sarray_realloc(struct sarray* array, int newsize) sarray_realloc (struct sarray *array, int newsize)
{ {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY; size_t old_max_index = (array->capacity - 1)/INDEX_CAPACITY;
size_t new_max_index = ((newsize-1)/INDEX_CAPACITY); size_t new_max_index = ((newsize - 1)/INDEX_CAPACITY);
size_t rounded_size = (new_max_index+1)*INDEX_CAPACITY; size_t rounded_size = (new_max_index + 1) * INDEX_CAPACITY;
struct sindex ** new_indices; struct sindex **new_indices;
struct sindex ** old_indices; struct sindex **old_indices;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE; size_t old_max_index = (array->capacity - 1)/BUCKET_SIZE;
size_t new_max_index = ((newsize-1)/BUCKET_SIZE); size_t new_max_index = ((newsize - 1)/BUCKET_SIZE);
size_t rounded_size = (new_max_index+1)*BUCKET_SIZE; size_t rounded_size = (new_max_index + 1) * BUCKET_SIZE;
struct sbucket ** new_buckets; struct sbucket **new_buckets;
struct sbucket ** old_buckets; struct sbucket **old_buckets;
#endif #endif
int counter; size_t counter;
assert(newsize > 0); assert (newsize > 0);
/* The size is the same, just ignore the request */ /* The size is the same, just ignore the request */
if(rounded_size <= array->capacity) if (rounded_size <= array->capacity)
return; return;
assert(array->ref_count == 1); /* stop if lazy copied... */ assert (array->ref_count == 1); /* stop if lazy copied... */
/* We are asked to extend the array -- allocate new bucket table, */ /* We are asked to extend the array -- allocate new bucket table, */
/* and insert empty_bucket in newly allocated places. */ /* and insert empty_bucket in newly allocated places. */
if(rounded_size > array->capacity) if (rounded_size > array->capacity)
{ {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
new_max_index += 4; new_max_index += 4;
rounded_size = (new_max_index+1)*INDEX_CAPACITY; rounded_size = (new_max_index + 1) * INDEX_CAPACITY;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
new_max_index += 4; new_max_index += 4;
rounded_size = (new_max_index+1)*BUCKET_SIZE; rounded_size = (new_max_index + 1) * BUCKET_SIZE;
#endif #endif
/* update capacity */ /* update capacity */
@ -332,16 +332,16 @@ sarray_realloc(struct sarray* array, int newsize)
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* alloc to force re-read by any concurrent readers. */ /* alloc to force re-read by any concurrent readers. */
old_indices = array->indices; old_indices = array->indices;
new_indices = (struct sindex**) new_indices = (struct sindex **)
objc_malloc((new_max_index+1)*sizeof(struct sindex*)); objc_malloc ((new_max_index + 1) * sizeof (struct sindex *));
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
old_buckets = array->buckets; old_buckets = array->buckets;
new_buckets = (struct sbucket**) new_buckets = (struct sbucket **)
objc_malloc((new_max_index+1)*sizeof(struct sbucket*)); objc_malloc ((new_max_index + 1) * sizeof (struct sbucket *));
#endif #endif
/* copy buckets below old_max_index (they are still valid) */ /* copy buckets below old_max_index (they are still valid) */
for(counter = 0; counter <= old_max_index; counter++ ) { for (counter = 0; counter <= old_max_index; counter++ ) {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
new_indices[counter] = old_indices[counter]; new_indices[counter] = old_indices[counter];
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
@ -351,11 +351,11 @@ sarray_realloc(struct sarray* array, int newsize)
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* reset entries above old_max_index to empty_bucket */ /* reset entries above old_max_index to empty_bucket */
for(counter = old_max_index+1; counter <= new_max_index; counter++) for (counter = old_max_index + 1; counter <= new_max_index; counter++)
new_indices[counter] = array->empty_index; new_indices[counter] = array->empty_index;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
/* reset entries above old_max_index to empty_bucket */ /* reset entries above old_max_index to empty_bucket */
for(counter = old_max_index+1; counter <= new_max_index; counter++) for (counter = old_max_index + 1; counter <= new_max_index; counter++)
new_buckets[counter] = array->empty_bucket; new_buckets[counter] = array->empty_bucket;
#endif #endif
@ -368,9 +368,9 @@ sarray_realloc(struct sarray* array, int newsize)
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* free the old indices */ /* free the old indices */
sarray_free_garbage(old_indices); sarray_free_garbage (old_indices);
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
sarray_free_garbage(old_buckets); sarray_free_garbage (old_buckets);
#endif #endif
idxsize += (new_max_index-old_max_index); idxsize += (new_max_index-old_max_index);
@ -382,20 +382,19 @@ sarray_realloc(struct sarray* array, int newsize)
/* Free a sparse array allocated with sarray_new */ /* Free a sparse array allocated with sarray_new */
void void
sarray_free(struct sarray* array) { sarray_free (struct sarray *array) {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY; size_t old_max_index = (array->capacity - 1)/INDEX_CAPACITY;
struct sindex ** old_indices; struct sindex **old_indices;
#else #else
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE; size_t old_max_index = (array->capacity - 1)/BUCKET_SIZE;
struct sbucket ** old_buckets; struct sbucket **old_buckets;
#endif #endif
int counter = 0; size_t counter = 0;
assert(array->ref_count != 0); /* Freed multiple times!!! */ assert (array->ref_count != 0); /* Freed multiple times!!! */
if(--(array->ref_count) != 0) /* There exists copies of me */ if (--(array->ref_count) != 0) /* There exists copies of me */
return; return;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
@ -404,34 +403,34 @@ sarray_free(struct sarray* array) {
old_buckets = array->buckets; old_buckets = array->buckets;
#endif #endif
if((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0)) if ((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
sarray_free(array->is_copy_of); sarray_free (array->is_copy_of);
/* Free all entries that do not point to empty_bucket */ /* Free all entries that do not point to empty_bucket */
for(counter = 0; counter <= old_max_index; counter++ ) { for (counter = 0; counter <= old_max_index; counter++ ) {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
struct sindex* idx = old_indices[counter]; struct sindex *idx = old_indices[counter];
if((idx != array->empty_index) && if ((idx != array->empty_index) &&
(idx->version.version == array->version.version)) { (idx->version.version == array->version.version)) {
int c2; int c2;
for(c2=0; c2<INDEX_SIZE; c2++) { for (c2 = 0; c2 < INDEX_SIZE; c2++) {
struct sbucket* bkt = idx->buckets[c2]; struct sbucket *bkt = idx->buckets[c2];
if((bkt != array->empty_bucket) && if ((bkt != array->empty_bucket) &&
(bkt->version.version == array->version.version)) (bkt->version.version == array->version.version))
{ {
sarray_free_garbage(bkt); sarray_free_garbage (bkt);
nbuckets -= 1; nbuckets -= 1;
} }
} }
sarray_free_garbage(idx); sarray_free_garbage (idx);
nindices -= 1; nindices -= 1;
} }
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
struct sbucket* bkt = array->buckets[counter]; struct sbucket *bkt = array->buckets[counter];
if ((bkt != array->empty_bucket) && if ((bkt != array->empty_bucket) &&
(bkt->version.version == array->version.version)) (bkt->version.version == array->version.version))
{ {
sarray_free_garbage(bkt); sarray_free_garbage (bkt);
nbuckets -= 1; nbuckets -= 1;
} }
#endif #endif
@ -439,52 +438,52 @@ sarray_free(struct sarray* array) {
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* free empty_index */ /* free empty_index */
if(array->empty_index->version.version == array->version.version) { if (array->empty_index->version.version == array->version.version) {
sarray_free_garbage(array->empty_index); sarray_free_garbage (array->empty_index);
nindices -= 1; nindices -= 1;
} }
#endif #endif
/* free empty_bucket */ /* free empty_bucket */
if(array->empty_bucket->version.version == array->version.version) { if (array->empty_bucket->version.version == array->version.version) {
sarray_free_garbage(array->empty_bucket); sarray_free_garbage (array->empty_bucket);
nbuckets -= 1; nbuckets -= 1;
} }
idxsize -= (old_max_index+1); idxsize -= (old_max_index + 1);
narrays -= 1; narrays -= 1;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* free bucket table */ /* free bucket table */
sarray_free_garbage(array->indices); sarray_free_garbage (array->indices);
#else #else
/* free bucket table */ /* free bucket table */
sarray_free_garbage(array->buckets); sarray_free_garbage (array->buckets);
#endif #endif
/* free array */ /* free array */
sarray_free_garbage(array); sarray_free_garbage (array);
} }
/* This is a lazy copy. Only the core of the structure is actually */ /* This is a lazy copy. Only the core of the structure is actually */
/* copied. */ /* copied. */
struct sarray* struct sarray *
sarray_lazy_copy(struct sarray* oarr) sarray_lazy_copy (struct sarray *oarr)
{ {
struct sarray* arr; struct sarray *arr;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1; size_t num_indices = ((oarr->capacity - 1)/INDEX_CAPACITY) + 1;
struct sindex ** new_indices; struct sindex **new_indices;
#else /* OBJC_SPARSE2 */ #else /* OBJC_SPARSE2 */
size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1; size_t num_indices = ((oarr->capacity - 1)/BUCKET_SIZE) + 1;
struct sbucket ** new_buckets; struct sbucket **new_buckets;
#endif #endif
/* Allocate core array */ /* Allocate core array */
arr = (struct sarray*) objc_malloc(sizeof(struct sarray)); /* !!! */ arr = (struct sarray *) objc_malloc (sizeof (struct sarray)); /* !!! */
arr->version.version = oarr->version.version + 1; arr->version.version = oarr->version.version + 1;
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
arr->empty_index = oarr->empty_index; arr->empty_index = oarr->empty_index;
@ -497,17 +496,15 @@ sarray_lazy_copy(struct sarray* oarr)
#ifdef OBJC_SPARSE3 #ifdef OBJC_SPARSE3
/* Copy bucket table */ /* Copy bucket table */
new_indices = (struct sindex**) new_indices = (struct sindex **)
objc_malloc(sizeof(struct sindex*)*num_indices); objc_malloc (sizeof (struct sindex *) * num_indices);
memcpy( new_indices,oarr->indices, memcpy (new_indices, oarr->indices, sizeof (struct sindex *) * num_indices);
sizeof(struct sindex*)*num_indices);
arr->indices = new_indices; arr->indices = new_indices;
#else #else
/* Copy bucket table */ /* Copy bucket table */
new_buckets = (struct sbucket**) new_buckets = (struct sbucket **)
objc_malloc(sizeof(struct sbucket*)*num_indices); objc_malloc (sizeof (struct sbucket *) * num_indices);
memcpy( new_buckets,oarr->buckets, memcpy (new_buckets, oarr->buckets, sizeof (struct sbucket *) * num_indices);
sizeof(struct sbucket*)*num_indices);
arr->buckets = new_buckets; arr->buckets = new_buckets;
#endif #endif

@ -1,5 +1,5 @@
/* GNU Objective C Runtime Thread Implementation /* GNU Objective C Runtime Thread Implementation
Copyright (C) 1996, 1997 Free Software Foundation, Inc. Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
Modified for Mach threads by Bill Bumgarner <bbum@friday.com> Modified for Mach threads by Bill Bumgarner <bbum@friday.com>
Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro> Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro>
@ -37,7 +37,8 @@ Boston, MA 02111-1307, USA. */
maximum priority downward only-- cannot be raised without superuser maximum priority downward only-- cannot be raised without superuser
privileges. Once lowered, it cannot be raised. privileges. Once lowered, it cannot be raised.
*/ */
static int __mach_get_max_thread_priority(cthread_t t, int *base) static int
__mach_get_max_thread_priority (cthread_t t, int *base)
{ {
thread_t threadP; thread_t threadP;
kern_return_t error; kern_return_t error;
@ -47,10 +48,10 @@ static int __mach_get_max_thread_priority(cthread_t t, int *base)
if (t == NULL) if (t == NULL)
return -1; return -1;
threadP = cthread_thread(t); /* get thread underlying */ threadP = cthread_thread (t); /* get thread underlying */
error=thread_info(threadP, THREAD_SCHED_INFO, error = thread_info (threadP, THREAD_SCHED_INFO,
(thread_info_t)&info, &info_count); (thread_info_t) &info, &info_count);
if (error != KERN_SUCCESS) if (error != KERN_SUCCESS)
return -1; return -1;
@ -65,14 +66,14 @@ static int __mach_get_max_thread_priority(cthread_t t, int *base)
/* Initialize the threads subsystem. */ /* Initialize the threads subsystem. */
int int
__objc_init_thread_system(void) __objc_init_thread_system (void)
{ {
return 0; return 0;
} }
/* Close the threads subsystem. */ /* Close the threads subsystem. */
int int
__objc_close_thread_system(void) __objc_close_thread_system (void)
{ {
return 0; return 0;
} }
@ -81,19 +82,19 @@ __objc_close_thread_system(void)
/* Create a new thread of execution. */ /* Create a new thread of execution. */
objc_thread_t objc_thread_t
__objc_thread_detach(void (*func)(void *arg), void *arg) __objc_thread_detach (void (*func) (void *arg), void *arg)
{ {
objc_thread_t thread_id; objc_thread_t thread_id;
cthread_t new_thread_handle; cthread_t new_thread_handle;
/* create thread */ /* create thread */
new_thread_handle = cthread_fork((cthread_fn_t)func, arg); new_thread_handle = cthread_fork ((cthread_fn_t) func, arg);
if(new_thread_handle) if (new_thread_handle)
{ {
/* this is not terribly portable */ /* this is not terribly portable */
thread_id = *(objc_thread_t *)&new_thread_handle; thread_id = *(objc_thread_t *) &new_thread_handle;
cthread_detach(new_thread_handle); cthread_detach (new_thread_handle);
} }
else else
thread_id = NULL; thread_id = NULL;
@ -103,11 +104,11 @@ __objc_thread_detach(void (*func)(void *arg), void *arg)
/* Set the current thread's priority. */ /* Set the current thread's priority. */
int int
__objc_thread_set_priority(int priority) __objc_thread_set_priority (int priority)
{ {
objc_thread_t *t = objc_thread_id(); objc_thread_t *t = objc_thread_id ();
cthread_t cT = (cthread_t) t; cthread_t cT = (cthread_t) t;
int maxPriority = __mach_get_max_thread_priority(cT, NULL); int maxPriority = __mach_get_max_thread_priority (cT, NULL);
int sys_priority = 0; int sys_priority = 0;
if (maxPriority == -1) if (maxPriority == -1)
@ -132,7 +133,7 @@ __objc_thread_set_priority(int priority)
return -1; return -1;
/* Change the priority */ /* Change the priority */
if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS) if (cthread_priority (cT, sys_priority, 0) == KERN_SUCCESS)
return 0; return 0;
else else
return -1; return -1;
@ -140,19 +141,19 @@ __objc_thread_set_priority(int priority)
/* Return the current thread's priority. */ /* Return the current thread's priority. */
int int
__objc_thread_get_priority(void) __objc_thread_get_priority (void)
{ {
objc_thread_t *t = objc_thread_id(); objc_thread_t *t = objc_thread_id ();
cthread_t cT = (cthread_t) t; /* see objc_thread_id() */ cthread_t cT = (cthread_t) t; /* see objc_thread_id () */
int basePriority; int basePriority;
int maxPriority; int maxPriority;
int sys_priority = 0; int sys_priority = 0;
int interactiveT, backgroundT, lowT; /* thresholds */ int interactiveT, backgroundT, lowT; /* thresholds */
maxPriority = __mach_get_max_thread_priority(cT, &basePriority); maxPriority = __mach_get_max_thread_priority (cT, &basePriority);
if(maxPriority == -1) if (maxPriority == -1)
return -1; return -1;
if (basePriority > ( (maxPriority * 2) / 3)) if (basePriority > ( (maxPriority * 2) / 3))
@ -166,17 +167,17 @@ __objc_thread_get_priority(void)
/* Yield our process time to another thread. */ /* Yield our process time to another thread. */
void void
__objc_thread_yield(void) __objc_thread_yield (void)
{ {
cthread_yield(); cthread_yield ();
} }
/* Terminate the current thread. */ /* Terminate the current thread. */
int int
__objc_thread_exit(void) __objc_thread_exit (void)
{ {
/* exit the thread */ /* exit the thread */
cthread_exit(&__objc_thread_exit_status); cthread_exit (&__objc_thread_exit_status);
/* Failed if we reached here */ /* Failed if we reached here */
return -1; return -1;
@ -184,42 +185,42 @@ __objc_thread_exit(void)
/* Returns an integer value which uniquely describes a thread. */ /* Returns an integer value which uniquely describes a thread. */
objc_thread_t objc_thread_t
__objc_thread_id(void) __objc_thread_id (void)
{ {
cthread_t self = cthread_self(); cthread_t self = cthread_self ();
return *(objc_thread_t *)&self; return *(objc_thread_t *) &self;
} }
/* Sets the thread's local storage pointer. */ /* Sets the thread's local storage pointer. */
int int
__objc_thread_set_data(void *value) __objc_thread_set_data (void *value)
{ {
cthread_set_data(cthread_self(), (any_t) value); cthread_set_data (cthread_self (), (any_t) value);
return 0; return 0;
} }
/* Returns the thread's local storage pointer. */ /* Returns the thread's local storage pointer. */
void * void *
__objc_thread_get_data(void) __objc_thread_get_data (void)
{ {
return (void *) cthread_data(cthread_self()); return (void *) cthread_data (cthread_self ());
} }
/* Backend mutex functions */ /* Backend mutex functions */
/* Allocate a mutex. */ /* Allocate a mutex. */
int int
__objc_mutex_allocate(objc_mutex_t mutex) __objc_mutex_allocate (objc_mutex_t mutex)
{ {
int err = 0; int err = 0;
mutex->backend = objc_malloc(sizeof(struct mutex)); mutex->backend = objc_malloc (sizeof (struct mutex));
err = mutex_init((mutex_t)(mutex->backend)); err = mutex_init ((mutex_t) (mutex->backend));
if (err != 0) if (err != 0)
{ {
objc_free(mutex->backend); objc_free (mutex->backend);
return -1; return -1;
} }
else else
@ -228,28 +229,28 @@ __objc_mutex_allocate(objc_mutex_t mutex)
/* Deallocate a mutex. */ /* Deallocate a mutex. */
int int
__objc_mutex_deallocate(objc_mutex_t mutex) __objc_mutex_deallocate (objc_mutex_t mutex)
{ {
mutex_clear((mutex_t)(mutex->backend)); mutex_clear ((mutex_t) (mutex->backend));
objc_free(mutex->backend); objc_free (mutex->backend);
mutex->backend = NULL; mutex->backend = NULL;
return 0; return 0;
} }
/* Grab a lock on a mutex. */ /* Grab a lock on a mutex. */
int int
__objc_mutex_lock(objc_mutex_t mutex) __objc_mutex_lock (objc_mutex_t mutex)
{ {
mutex_lock((mutex_t)(mutex->backend)); mutex_lock ((mutex_t) (mutex->backend));
return 0; return 0;
} }
/* Try to grab a lock on a mutex. */ /* Try to grab a lock on a mutex. */
int int
__objc_mutex_trylock(objc_mutex_t mutex) __objc_mutex_trylock (objc_mutex_t mutex)
{ {
if (mutex_try_lock((mutex_t)(mutex->backend)) == 0) if (mutex_try_lock ((mutex_t) (mutex->backend)) == 0)
return -1; return -1;
else else
return 0; return 0;
@ -257,9 +258,9 @@ __objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */ /* Unlock the mutex */
int int
__objc_mutex_unlock(objc_mutex_t mutex) __objc_mutex_unlock (objc_mutex_t mutex)
{ {
mutex_unlock((mutex_t)(mutex->backend)); mutex_unlock ((mutex_t) (mutex->backend));
return 0; return 0;
} }
@ -267,45 +268,45 @@ __objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */ /* Allocate a condition. */
int int
__objc_condition_allocate(objc_condition_t condition) __objc_condition_allocate (objc_condition_t condition)
{ {
condition->backend = objc_malloc(sizeof(struct condition)); condition->backend = objc_malloc (sizeof (struct condition));
condition_init((condition_t)(condition->backend)); condition_init ((condition_t) (condition->backend));
return 0; return 0;
} }
/* Deallocate a condition. */ /* Deallocate a condition. */
int int
__objc_condition_deallocate(objc_condition_t condition) __objc_condition_deallocate (objc_condition_t condition)
{ {
condition_clear((condition_t)(condition->backend)); condition_clear ((condition_t) (condition->backend));
objc_free(condition->backend); objc_free (condition->backend);
condition->backend = NULL; condition->backend = NULL;
return 0; return 0;
} }
/* Wait on the condition */ /* Wait on the condition */
int int
__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) __objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{ {
condition_wait((condition_t)(condition->backend), condition_wait ((condition_t) (condition->backend),
(mutex_t)(mutex->backend)); (mutex_t) (mutex->backend));
return 0; return 0;
} }
/* Wake up all threads waiting on this condition. */ /* Wake up all threads waiting on this condition. */
int int
__objc_condition_broadcast(objc_condition_t condition) __objc_condition_broadcast (objc_condition_t condition)
{ {
condition_broadcast((condition_t)(condition->backend)); condition_broadcast ((condition_t) (condition->backend));
return 0; return 0;
} }
/* Wake up one thread waiting on this condition. */ /* Wake up one thread waiting on this condition. */
int int
__objc_condition_signal(objc_condition_t condition) __objc_condition_signal (objc_condition_t condition)
{ {
condition_signal((condition_t)(condition->backend)); condition_signal ((condition_t) (condition->backend));
return 0; return 0;
} }

@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */
#define _LIBOBJC #define _LIBOBJC
#include "tconfig.h" #include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
#include "defaults.h" #include "defaults.h"
#include <objc/thr.h> #include <objc/thr.h>
#include "runtime.h" #include "runtime.h"

178
thr.c

@ -48,7 +48,7 @@ objc_thread_callback _objc_became_multi_threaded = NULL;
it can be informed; for example, the GNUstep Base Library sets it it can be informed; for example, the GNUstep Base Library sets it
so it can implement the NSBecomingMultiThreaded notification. so it can implement the NSBecomingMultiThreaded notification.
*/ */
objc_thread_callback objc_set_thread_callback(objc_thread_callback func) objc_thread_callback objc_set_thread_callback (objc_thread_callback func)
{ {
objc_thread_callback temp = _objc_became_multi_threaded; objc_thread_callback temp = _objc_became_multi_threaded;
_objc_became_multi_threaded = func; _objc_became_multi_threaded = func;
@ -76,44 +76,44 @@ struct __objc_thread_start_state
}; };
static volatile void static volatile void
__objc_thread_detach_function(struct __objc_thread_start_state *istate) __objc_thread_detach_function (struct __objc_thread_start_state *istate)
{ {
/* Valid state? */ /* Valid state? */
if (istate) { if (istate) {
id (*imp)(id,SEL,id); id (*imp) (id, SEL, id);
SEL selector = istate->selector; SEL selector = istate->selector;
id object = istate->object; id object = istate->object;
id argument = istate->argument; id argument = istate->argument;
/* Don't need anymore so free it */ /* Don't need anymore so free it */
objc_free(istate); objc_free (istate);
/* Clear out the thread local storage */ /* Clear out the thread local storage */
objc_thread_set_data(NULL); objc_thread_set_data (NULL);
/* Check to see if we just became multi threaded */ /* Check to see if we just became multi threaded */
if (!__objc_is_multi_threaded) if (! __objc_is_multi_threaded)
{ {
__objc_is_multi_threaded = 1; __objc_is_multi_threaded = 1;
/* Call the hook function */ /* Call the hook function */
if (_objc_became_multi_threaded != NULL) if (_objc_became_multi_threaded != NULL)
(*_objc_became_multi_threaded)(); (*_objc_became_multi_threaded) ();
} }
/* Call the method */ /* Call the method */
if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector))) if ((imp = (id (*) (id, SEL, id))objc_msg_lookup (object, selector)))
(*imp)(object, selector, argument); (*imp) (object, selector, argument);
else else
objc_error(object, OBJC_ERR_UNIMPLEMENTED, objc_error (object, OBJC_ERR_UNIMPLEMENTED,
"objc_thread_detach called with bad selector.\n"); "objc_thread_detach called with bad selector.\n");
} }
else else
objc_error(nil, OBJC_ERR_BAD_STATE, objc_error (nil, OBJC_ERR_BAD_STATE,
"objc_thread_detach called with NULL state.\n"); "objc_thread_detach called with NULL state.\n");
/* Exit the thread */ /* Exit the thread */
objc_thread_exit(); objc_thread_exit ();
} }
/* /*
@ -131,14 +131,14 @@ __objc_thread_detach_function(struct __objc_thread_start_state *istate)
takes a single argument. takes a single argument.
*/ */
objc_thread_t objc_thread_t
objc_thread_detach(SEL selector, id object, id argument) objc_thread_detach (SEL selector, id object, id argument)
{ {
struct __objc_thread_start_state *istate; struct __objc_thread_start_state *istate;
objc_thread_t thread_id = NULL; objc_thread_t thread_id = NULL;
/* Allocate the state structure */ /* Allocate the state structure */
if (!(istate = (struct __objc_thread_start_state *) if (! (istate = (struct __objc_thread_start_state *)
objc_malloc(sizeof(*istate)))) objc_malloc (sizeof (*istate))))
return NULL; return NULL;
/* Initialize the state structure */ /* Initialize the state structure */
@ -147,39 +147,39 @@ objc_thread_detach(SEL selector, id object, id argument)
istate->argument = argument; istate->argument = argument;
/* lock access */ /* lock access */
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
/* Call the backend to spawn the thread */ /* Call the backend to spawn the thread */
if ((thread_id = __objc_thread_detach((void *)__objc_thread_detach_function, if ((thread_id = __objc_thread_detach ((void *)__objc_thread_detach_function,
istate)) == NULL) istate)) == NULL)
{ {
/* failed! */ /* failed! */
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
objc_free(istate); objc_free (istate);
return NULL; return NULL;
} }
/* Increment our thread counter */ /* Increment our thread counter */
__objc_runtime_threads_alive++; __objc_runtime_threads_alive++;
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
return thread_id; return thread_id;
} }
/* Set the current thread's priority. */ /* Set the current thread's priority. */
int int
objc_thread_set_priority(int priority) objc_thread_set_priority (int priority)
{ {
/* Call the backend */ /* Call the backend */
return __objc_thread_set_priority(priority); return __objc_thread_set_priority (priority);
} }
/* Return the current thread's priority. */ /* Return the current thread's priority. */
int int
objc_thread_get_priority(void) objc_thread_get_priority (void)
{ {
/* Call the backend */ /* Call the backend */
return __objc_thread_get_priority(); return __objc_thread_get_priority ();
} }
/* /*
@ -188,10 +188,10 @@ objc_thread_get_priority(void)
make progress even on a lazy uniprocessor system. make progress even on a lazy uniprocessor system.
*/ */
void void
objc_thread_yield(void) objc_thread_yield (void)
{ {
/* Call the backend */ /* Call the backend */
__objc_thread_yield(); __objc_thread_yield ();
} }
/* /*
@ -199,15 +199,15 @@ objc_thread_yield(void)
Actually, if it failed returns -1. Actually, if it failed returns -1.
*/ */
int int
objc_thread_exit(void) objc_thread_exit (void)
{ {
/* Decrement our counter of the number of threads alive */ /* Decrement our counter of the number of threads alive */
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
__objc_runtime_threads_alive--; __objc_runtime_threads_alive--;
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
/* Call the backend to terminate the thread */ /* Call the backend to terminate the thread */
return __objc_thread_exit(); return __objc_thread_exit ();
} }
/* /*
@ -215,10 +215,10 @@ objc_thread_exit(void)
NULL which is reserved as a marker for "no thread". NULL which is reserved as a marker for "no thread".
*/ */
objc_thread_t objc_thread_t
objc_thread_id(void) objc_thread_id (void)
{ {
/* Call the backend */ /* Call the backend */
return __objc_thread_id(); return __objc_thread_id ();
} }
/* /*
@ -226,20 +226,20 @@ objc_thread_id(void)
Returns 0 if successful or -1 if failed. Returns 0 if successful or -1 if failed.
*/ */
int int
objc_thread_set_data(void *value) objc_thread_set_data (void *value)
{ {
/* Call the backend */ /* Call the backend */
return __objc_thread_set_data(value); return __objc_thread_set_data (value);
} }
/* /*
Returns the thread's local storage pointer. Returns NULL on failure. Returns the thread's local storage pointer. Returns NULL on failure.
*/ */
void * void *
objc_thread_get_data(void) objc_thread_get_data (void)
{ {
/* Call the backend */ /* Call the backend */
return __objc_thread_get_data(); return __objc_thread_get_data ();
} }
/* Frontend mutex functions */ /* Frontend mutex functions */
@ -249,19 +249,19 @@ objc_thread_get_data(void)
allocation failed for any reason. allocation failed for any reason.
*/ */
objc_mutex_t objc_mutex_t
objc_mutex_allocate(void) objc_mutex_allocate (void)
{ {
objc_mutex_t mutex; objc_mutex_t mutex;
/* Allocate the mutex structure */ /* Allocate the mutex structure */
if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex)))) if (! (mutex = (objc_mutex_t)objc_malloc (sizeof (struct objc_mutex))))
return NULL; return NULL;
/* Call backend to create the mutex */ /* Call backend to create the mutex */
if (__objc_mutex_allocate(mutex)) if (__objc_mutex_allocate (mutex))
{ {
/* failed! */ /* failed! */
objc_free(mutex); objc_free (mutex);
return NULL; return NULL;
} }
@ -279,23 +279,23 @@ objc_mutex_allocate(void)
Returns the number of locks on the thread. (1 for deallocate). Returns the number of locks on the thread. (1 for deallocate).
*/ */
int int
objc_mutex_deallocate(objc_mutex_t mutex) objc_mutex_deallocate (objc_mutex_t mutex)
{ {
int depth; int depth;
/* Valid mutex? */ /* Valid mutex? */
if (!mutex) if (! mutex)
return -1; return -1;
/* Acquire lock on mutex */ /* Acquire lock on mutex */
depth = objc_mutex_lock(mutex); depth = objc_mutex_lock (mutex);
/* Call backend to destroy mutex */ /* Call backend to destroy mutex */
if (__objc_mutex_deallocate(mutex)) if (__objc_mutex_deallocate (mutex))
return -1; return -1;
/* Free the mutex structure */ /* Free the mutex structure */
objc_free(mutex); objc_free (mutex);
/* Return last depth */ /* Return last depth */
return depth; return depth;
@ -308,22 +308,22 @@ objc_mutex_deallocate(objc_mutex_t mutex)
Returns the lock count on the mutex held by this thread. Returns the lock count on the mutex held by this thread.
*/ */
int int
objc_mutex_lock(objc_mutex_t mutex) objc_mutex_lock (objc_mutex_t mutex)
{ {
objc_thread_t thread_id; objc_thread_t thread_id;
int status; int status;
/* Valid mutex? */ /* Valid mutex? */
if (!mutex) if (! mutex)
return -1; return -1;
/* If we already own the lock then increment depth */ /* If we already own the lock then increment depth */
thread_id = objc_thread_id(); thread_id = __objc_thread_id ();
if (mutex->owner == thread_id) if (mutex->owner == thread_id)
return ++mutex->depth; return ++mutex->depth;
/* Call the backend to lock the mutex */ /* Call the backend to lock the mutex */
status = __objc_mutex_lock(mutex); status = __objc_mutex_lock (mutex);
/* Failed? */ /* Failed? */
if (status) if (status)
@ -340,22 +340,22 @@ objc_mutex_lock(objc_mutex_t mutex)
thread has a lock on the mutex returns -1. thread has a lock on the mutex returns -1.
*/ */
int int
objc_mutex_trylock(objc_mutex_t mutex) objc_mutex_trylock (objc_mutex_t mutex)
{ {
objc_thread_t thread_id; objc_thread_t thread_id;
int status; int status;
/* Valid mutex? */ /* Valid mutex? */
if (!mutex) if (! mutex)
return -1; return -1;
/* If we already own the lock then increment depth */ /* If we already own the lock then increment depth */
thread_id = objc_thread_id(); thread_id = __objc_thread_id ();
if (mutex->owner == thread_id) if (mutex->owner == thread_id)
return ++mutex->depth; return ++mutex->depth;
/* Call the backend to try to lock the mutex */ /* Call the backend to try to lock the mutex */
status = __objc_mutex_trylock(mutex); status = __objc_mutex_trylock (mutex);
/* Failed? */ /* Failed? */
if (status) if (status)
@ -375,17 +375,17 @@ objc_mutex_trylock(objc_mutex_t mutex)
doesn't hold in which case return -1 and the mutex is unaffected. doesn't hold in which case return -1 and the mutex is unaffected.
*/ */
int int
objc_mutex_unlock(objc_mutex_t mutex) objc_mutex_unlock (objc_mutex_t mutex)
{ {
objc_thread_t thread_id; objc_thread_t thread_id;
int status; int status;
/* Valid mutex? */ /* Valid mutex? */
if (!mutex) if (! mutex)
return -1; return -1;
/* If another thread owns the lock then abort */ /* If another thread owns the lock then abort */
thread_id = objc_thread_id(); thread_id = __objc_thread_id ();
if (mutex->owner != thread_id) if (mutex->owner != thread_id)
return -1; return -1;
@ -398,7 +398,7 @@ objc_mutex_unlock(objc_mutex_t mutex)
mutex->owner = NULL; mutex->owner = NULL;
/* Have the backend unlock the mutex */ /* Have the backend unlock the mutex */
status = __objc_mutex_unlock(mutex); status = __objc_mutex_unlock (mutex);
/* Failed? */ /* Failed? */
if (status) if (status)
@ -414,20 +414,20 @@ objc_mutex_unlock(objc_mutex_t mutex)
if the allocation failed for any reason. if the allocation failed for any reason.
*/ */
objc_condition_t objc_condition_t
objc_condition_allocate(void) objc_condition_allocate (void)
{ {
objc_condition_t condition; objc_condition_t condition;
/* Allocate the condition mutex structure */ /* Allocate the condition mutex structure */
if (!(condition = if (! (condition =
(objc_condition_t)objc_malloc(sizeof(struct objc_condition)))) (objc_condition_t) objc_malloc (sizeof (struct objc_condition))))
return NULL; return NULL;
/* Call the backend to create the condition mutex */ /* Call the backend to create the condition mutex */
if (__objc_condition_allocate(condition)) if (__objc_condition_allocate (condition))
{ {
/* failed! */ /* failed! */
objc_free(condition); objc_free (condition);
return NULL; return NULL;
} }
@ -443,41 +443,41 @@ objc_condition_allocate(void)
waiting but just wake them up. waiting but just wake them up.
*/ */
int int
objc_condition_deallocate(objc_condition_t condition) objc_condition_deallocate (objc_condition_t condition)
{ {
/* Broadcast the condition */ /* Broadcast the condition */
if (objc_condition_broadcast(condition)) if (objc_condition_broadcast (condition))
return -1; return -1;
/* Call the backend to destroy */ /* Call the backend to destroy */
if (__objc_condition_deallocate(condition)) if (__objc_condition_deallocate (condition))
return -1; return -1;
/* Free the condition mutex structure */ /* Free the condition mutex structure */
objc_free(condition); objc_free (condition);
return 0; return 0;
} }
/* /*
Wait on the condition unlocking the mutex until objc_condition_signal() Wait on the condition unlocking the mutex until objc_condition_signal ()
or objc_condition_broadcast() are called for the same condition. The or objc_condition_broadcast () are called for the same condition. The
given mutex *must* have the depth set to 1 so that it can be unlocked given mutex *must* have the depth set to 1 so that it can be unlocked
here, so that someone else can lock it and signal/broadcast the condition. here, so that someone else can lock it and signal/broadcast the condition.
The mutex is used to lock access to the shared data that make up the The mutex is used to lock access to the shared data that make up the
"condition" predicate. "condition" predicate.
*/ */
int int
objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{ {
objc_thread_t thread_id; objc_thread_t thread_id;
/* Valid arguments? */ /* Valid arguments? */
if (!mutex || !condition) if (! mutex || ! condition)
return -1; return -1;
/* Make sure we are owner of mutex */ /* Make sure we are owner of mutex */
thread_id = objc_thread_id(); thread_id = __objc_thread_id ();
if (mutex->owner != thread_id) if (mutex->owner != thread_id)
return -1; return -1;
@ -490,7 +490,7 @@ objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
mutex->owner = (objc_thread_t)NULL; mutex->owner = (objc_thread_t)NULL;
/* Call the backend to wait */ /* Call the backend to wait */
__objc_condition_wait(condition, mutex); __objc_condition_wait (condition, mutex);
/* Make ourselves owner of the mutex */ /* Make ourselves owner of the mutex */
mutex->owner = thread_id; mutex->owner = thread_id;
@ -506,13 +506,13 @@ objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
right away after this call. right away after this call.
*/ */
int int
objc_condition_broadcast(objc_condition_t condition) objc_condition_broadcast (objc_condition_t condition)
{ {
/* Valid condition mutex? */ /* Valid condition mutex? */
if (!condition) if (! condition)
return -1; return -1;
return __objc_condition_broadcast(condition); return __objc_condition_broadcast (condition);
} }
/* /*
@ -522,42 +522,42 @@ objc_condition_broadcast(objc_condition_t condition)
right away after this call. right away after this call.
*/ */
int int
objc_condition_signal(objc_condition_t condition) objc_condition_signal (objc_condition_t condition)
{ {
/* Valid condition mutex? */ /* Valid condition mutex? */
if (!condition) if (! condition)
return -1; return -1;
return __objc_condition_signal(condition); return __objc_condition_signal (condition);
} }
/* Make the objc thread system aware that a thread which is managed /* Make the objc thread system aware that a thread which is managed
(started, stopped) by external code could access objc facilities (started, stopped) by external code could access objc facilities
from now on. This is used when you are interfacing with some from now on. This is used when you are interfacing with some
external non-objc-based environment/system - you must call external non-objc-based environment/system - you must call
objc_thread_add() before an alien thread makes any calls to objc_thread_add () before an alien thread makes any calls to
Objective-C. Do not cause the _objc_became_multi_threaded hook to Objective-C. Do not cause the _objc_became_multi_threaded hook to
be executed. */ be executed. */
void void
objc_thread_add(void) objc_thread_add (void)
{ {
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
__objc_is_multi_threaded = 1; __objc_is_multi_threaded = 1;
__objc_runtime_threads_alive++; __objc_runtime_threads_alive++;
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
/* Make the objc thread system aware that a thread managed (started, /* Make the objc thread system aware that a thread managed (started,
stopped) by some external code will no longer access objc and thus stopped) by some external code will no longer access objc and thus
can be forgotten by the objc thread system. Call can be forgotten by the objc thread system. Call
objc_thread_remove() when your alien thread is done with making objc_thread_remove () when your alien thread is done with making
calls to Objective-C. */ calls to Objective-C. */
void void
objc_thread_remove(void) objc_thread_remove (void)
{ {
objc_mutex_lock(__objc_runtime_mutex); objc_mutex_lock (__objc_runtime_mutex);
__objc_runtime_threads_alive--; __objc_runtime_threads_alive--;
objc_mutex_unlock(__objc_runtime_mutex); objc_mutex_unlock (__objc_runtime_mutex);
} }
/* End of File */ /* End of File */

Loading…
Cancel
Save