Commit 4109fe85 by Bryce McKinlay Committed by Bryce McKinlay

configure.in (GCINCS): Don't use "boehm-cflags".

libjava:
2004-08-13  Bryce McKinlay  <mckinlay@redhat.com>

	* configure.in (GCINCS): Don't use "boehm-cflags". Instead, -I
	boehm-gc's include dirs.
	* configure: Rebuilt.
	* include/boehm-gc.h: Include gc_config.h.

boehm-gc:
2004-08-13  Bryce McKinlay  <mckinlay@redhat.com>

	* configure.ac (gc_cflags): Add -Iinclude.
	(AC_CONFIG_HEADERS): New. Configure gc_config.h header.
	Don't write DEFS to boehm-cflags file.
	* configure: Rebuilt.
	* gcj_mlc.c: Check #ifdef GC_GCJ_SUPPORT after including headers.
	* specific.c: Check #ifdef GC_LINUX_THREADS after including headers.
	* include/gc_config_macros.h: Remove backward-compatibility
	redefinitions of GC_ names.
	* include/gc.h: Include <gc_config.h>.

2004-08-13  Bryce McKinlay  <mckinlay@redhat.com>

	Import Boehm GC version 6.3.

From-SVN: r85972
parent f13bb199
......@@ -16,7 +16,7 @@ link= $(bcbin)\ilink32
cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \
-w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0
#defines= -DSILENT
defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
defines= -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
.c.obj:
$(cc) @&&|
......
2004-08-13 Bryce McKinlay <mckinlay@redhat.com>
* configure.ac (gc_cflags): Add -Iinclude.
(AC_CONFIG_HEADERS): New. Configure gc_config.h header.
Don't write DEFS to boehm-cflags file.
* configure: Rebuilt.
* gcj_mlc.c: Check #ifdef GC_GCJ_SUPPORT after including headers.
* specific.c: Check #ifdef GC_LINUX_THREADS after including headers.
* include/gc_config_macros.h: Remove backward-compatibility
redefinitions of GC_ names.
* include/gc.h: Include <gc_config.h>.
2004-08-13 Bryce McKinlay <mckinlay@redhat.com>
Import Boehm GC version 6.3.
2004-08-12 Kelley Cook <kcook@gcc.gnu.org>
* include/Makefile.in: Regenerate
......
......@@ -36,7 +36,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
# To build the parallel collector in a static library on HP/UX,
# add to the above:
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -DUSE_HPUX_TLS -D_POSIX_C_SOURCE=199506L
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L
# To build the thread-safe collector on Tru64, add to the above:
# -pthread -DGC_OSF1_THREADS
......@@ -182,7 +182,7 @@ HOSTCFLAGS=$(CFLAGS)
# this facility is only used in a few places. It is intended primarily
# for debugging of the garbage collector itself, but could also
# -DDBG_HDRS_ALL Make sure that all objects have debug headers. Increases
# the reliability (from 99.9999% to 100%) of some of the debugging
# the reliability (from 99.9999% to 100% mod. bugs) of some of the debugging
# code (especially KEEP_BACK_PTRS). Makes -DSHORT_DBG_HDRS possible.
# Assumes that all client allocation is done through debugging
# allocators.
......@@ -235,6 +235,10 @@ HOSTCFLAGS=$(CFLAGS)
# in a way that usually does not involve acquisition of a global lock.
# Currently requires -DGC_LINUX_THREADS, but should be easy to port to
# other pthreads environments. Recommended for multiprocessors.
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
# "__thread" thread-local variables. This is the default in HP/UX. It
# may help performance on recent Linux installations. (It failed for
# me on RedHat 8, but appears to work on RedHat 9.)
# -DPARALLEL_MARK allows the marker to run in multiple threads. Recommended
# for multiprocessors. Currently requires Linux on X86 or IA64, though
# support for other Posix platforms should be fairly easy to add,
......@@ -316,14 +320,15 @@ DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
doc/README.environment doc/tree.html doc/gcdescr.html \
doc/README.autoconf doc/README.macros doc/README.ews4800 \
doc/README.DGUX386 doc/README.arm.cross doc/leak.html \
doc/scale.html doc/gcinterface.html doc/README.darwin
doc/scale.html doc/gcinterface.html doc/README.darwin \
doc/simple_example.html
TESTS= tests/test.c tests/test_cpp.cc tests/trace_test.c \
tests/leak_test.c tests/thread_leak_test.c
tests/leak_test.c tests/thread_leak_test.c tests/middle.c
GNU_BUILD_FILES= configure.in Makefile.am configure acinclude.m4 \
libtool.m4 install-sh configure.host Makefile.in \
ltconfig aclocal.m4 config.sub config.guess \
aclocal.m4 config.sub config.guess \
include/Makefile.am include/Makefile.in \
doc/Makefile.am doc/Makefile.in \
ltmain.sh mkinstalldirs depcomp missing
......@@ -331,7 +336,7 @@ GNU_BUILD_FILES= configure.in Makefile.am configure acinclude.m4 \
OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE gc.mak \
BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE Makefile.dj \
PCR-Makefile SMakefile.amiga Makefile.DLLs \
digimars.mak Makefile.direct
digimars.mak Makefile.direct NT_STATIC_THREADS_MAKEFILE
# Makefile and Makefile.direct are copies of each other.
OTHER_FILES= Makefile setjmp_t.c callprocs pc_excludes \
......@@ -363,16 +368,23 @@ SPECIALCFLAGS = -I$(srcdir)/include
all: gc.a gctest
BSD-pkg-all: bsd-libgc.a
LEAKFLAGS=$(CFLAGS) -DFIND_LEAK
BSD-pkg-all: bsd-libgc.a bsd-libleak.a
bsd-libgc.a:
$(MAKE) CFLAGS="$(CFLAGS)" clean c++-t
mv gc.a bsd-libgc.a
bsd-libleak.a:
$(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
mv gc.a bsd-libleak.a
BSD-pkg-install: BSD-pkg-all
${CP} bsd-libgc.a libgc.a
${INSTALL_DATA} libgc.a ${PREFIX}/lib
${INSTALL_DATA} gc.h gc_cpp.h ${PREFIX}/include
${INSTALL_MAN} doc/gc.man ${PREFIX}/man/man3/gc.3
pcr: PCR-Makefile include/private/gc_private.h include/private/gc_hdrs.h \
include/private/gc_locks.h include/gc.h include/private/gcconfig.h \
......
......@@ -29,7 +29,7 @@ EXE_SUFFIX=.exe
srcdir= .
VPATH= $(srcdir)
CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION -DSILENT
CFLAGS= -gstabs+ -O2 -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION -DSILENT
# Setjmp_test may yield overly optimistic results when compiled
# without optimization.
......@@ -157,9 +157,9 @@ AR= ar
RANLIB= ranlib
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o hpux_irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c hpux_irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC cord/SCOPTIONS.amiga cord/SMakefile.amiga
......@@ -181,7 +181,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.S rs6000_mach_dep.s alpha_mach_dep.S \
include/leak_detector.h $(CORD_SRCS)
OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
README test.c test_cpp.cc setjmp_t.c SMakefile.amiga \
README tests/test.c test_cpp.cc setjmp_t.c SMakefile.amiga \
SCoptions.amiga README.amiga README.win32 cord/README \
README.rs6000 README.QUICK callprocs pc_excludes \
barrett_diagram README.OS2 README.Mac MacProjects.sit.hqx \
......@@ -206,7 +206,7 @@ CURSES= -lcurses -ltermlib
# the SHELL environment variable.
SHELL= /bin/sh
SPECIALCFLAGS =
SPECIALCFLAGS = -I$(srcdir)/include
# Alternative flags to the C compiler for mach_dep.c.
# Mach_dep.c often doesn't like optimization, and it's
# not time-critical anyway.
......@@ -224,7 +224,7 @@ $(OBJS) test.o dyn_load.o dyn_load_sunos53.o: \
# options such as -DSILENT affects the size of GC_arrays,
# invalidating all .o files that rely on gc_priv.h
mark.o typd_mlc.o finalize.o: $(srcdir)/gc_mark.h
mark.o typd_mlc.o finalize.o: $(srcdir)/include/gc_mark.h
base_lib gc.a: $(OBJS) dyn_load.o $(UTILS)
echo > base_lib
......@@ -366,11 +366,11 @@ clean:
rm -f threadlibs$(EXE_SUFFIX) cord/cordtest$(EXE_SUFFIX)
-rm -f *~
gctest$(EXE_SUFFIX): test.o gc.a if_mach$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX)
gctest$(EXE_SUFFIX): tests/test.o gc.a if_mach$(EXE_SUFFIX) if_not_there$(EXE_SUFFIX)
rm -f gctest gctest$(EXE_SUFFIX)
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest test.o gc.a -lucb
./if_mach HP_PA "" $(CC) $(CFLAGS) -o gctest test.o gc.a -ldld
./if_not_there gctest$(EXE_SUFFIX) $(CC) $(CFLAGS) -o gctest$(EXE_SUFFIX) test.o gc.a
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -lucb
./if_mach HP_PA "" $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -ldld
./if_not_there gctest$(EXE_SUFFIX) $(CC) $(CFLAGS) -o gctest$(EXE_SUFFIX) tests/test.o gc.a
rm -f gctest
# If an optimized setjmp_test generates a segmentation fault,
......@@ -407,8 +407,8 @@ gc.tar.Z: gc.tar
gc.tar.gz: gc.tar
gzip gc.tar
lint: $(CSRCS) test.c
lint -DLINT $(CSRCS) test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall"
lint: $(CSRCS) tests/test.c
lint -DLINT $(CSRCS) tests/test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall"
# BTL: added to test shared library version of collector.
# Currently works only under SunOS5. Requires GC_INIT call from statically
......@@ -417,8 +417,8 @@ ABSDIR = `pwd`
gctest_dyn_link: test.o libgc.so
$(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link test.o -lgc -ldl -lthread
test_dll.o: test.c libgc_globals.h
$(CC) $(CFLAGS) -DGC_USE_DLL -c test.c -o test_dll.o
test_dll.o: tests/test.c libgc_globals.h
$(CC) $(CFLAGS) -DGC_USE_DLL -c tests/test.c -o test_dll.o
test_dll: test_dll.o libgc_dll.a libgc.dll
$(CC) test_dll.o -L$(ABSDIR) -lgc_dll -o test_dll
......
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.9 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
......@@ -81,15 +81,6 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__libgcjgc_la_SOURCES_DIST = allchblk.c alloc.c blacklst.c \
checksums.c dbg_mlc.c dyn_load.c finalize.c gc_dlopen.c \
gcj_mlc.c headers.c aix_irix_threads.c malloc.c mallocx.c \
mark.c mark_rts.c misc.c new_hblk.c obj_map.c os_dep.c \
pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
solaris_pthreads.c solaris_threads.c specific.c stubborn.c \
typd_mlc.c backgraph.c win32_threads.c pthread_support.c \
pthread_stop_world.c darwin_stop_world.c \
powerpc_darwin_mach_dep.s
@POWERPC_DARWIN_TRUE@am__objects_1 = powerpc_darwin_mach_dep.lo
am__objects_2 = allchblk.lo alloc.lo blacklst.lo checksums.lo \
dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
......@@ -101,15 +92,6 @@ am__objects_2 = allchblk.lo alloc.lo blacklst.lo checksums.lo \
pthread_stop_world.lo darwin_stop_world.lo $(am__objects_1)
am_libgcjgc_la_OBJECTS = $(am__objects_2)
libgcjgc_la_OBJECTS = $(am_libgcjgc_la_OBJECTS)
am__libgcjgc_convenience_la_SOURCES_DIST = allchblk.c alloc.c \
blacklst.c checksums.c dbg_mlc.c dyn_load.c finalize.c \
gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c malloc.c \
mallocx.c mark.c mark_rts.c misc.c new_hblk.c obj_map.c \
os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
solaris_pthreads.c solaris_threads.c specific.c stubborn.c \
typd_mlc.c backgraph.c win32_threads.c pthread_support.c \
pthread_stop_world.c darwin_stop_world.c \
powerpc_darwin_mach_dep.s
am_libgcjgc_convenience_la_OBJECTS = $(am__objects_2)
libgcjgc_convenience_la_OBJECTS = \
$(am_libgcjgc_convenience_la_OBJECTS)
......@@ -129,8 +111,6 @@ LTCCASCOMPILE = $(LIBTOOL) --mode=compile $(CCAS) $(AM_CCASFLAGS) \
$(CCASFLAGS)
SOURCES = $(libgcjgc_la_SOURCES) $(libgcjgc_convenience_la_SOURCES) \
$(gctest_SOURCES)
DIST_SOURCES = $(am__libgcjgc_la_SOURCES_DIST) \
$(am__libgcjgc_convenience_la_SOURCES_DIST) $(gctest_SOURCES)
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
......@@ -227,6 +207,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
......@@ -430,15 +412,6 @@ distclean-compile:
.c.lo:
$(LTCOMPILE) -c -o $@ $<
tests/test.o: tests/test.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test.o `test -f 'tests/test.c' || echo '$(srcdir)/'`tests/test.c
tests/test.obj: tests/test.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test.obj `if test -f 'tests/test.c'; then $(CYGPATH_W) 'tests/test.c'; else $(CYGPATH_W) '$(srcdir)/tests/test.c'; fi`
tests/test.lo: tests/test.c
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tests/test.lo `test -f 'tests/test.c' || echo '$(srcdir)/'`tests/test.c
.s.o:
$(CCASCOMPILE) -c $<
......@@ -454,19 +427,22 @@ clean-libtool:
distclean-libtool:
-rm -f libtool
# GNU Make needs to see an explicit $(MAKE) variable in the command it
# runs to enable its job server during parallel builds. Hence the
# comments below.
all-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do
$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
install-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do
$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
mostlyclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
distclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
maintainer-clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
uninstall-info-am:
# This directory's subdirectories are mostly independent; you can cd
......@@ -686,7 +662,7 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-rm -f tests/$(am__dirstamp)
maintainer-clean-generic:
......
......@@ -2,7 +2,8 @@
# DLLs are included in the root set under NT, but not under win32S.
# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
CPU= i386
MY_CPU=X86
CPU=$(MY_CPU)
!include <ntwin32.mak>
OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj
......@@ -10,10 +11,10 @@ OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_r
all: gctest.exe cord\de.exe test_cpp.exe
.c.obj:
$(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL $*.c /Fo$*.obj
$(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_BUILD $*.c /Fo$*.obj
.cpp.obj:
$(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP /Fo$*.obj
$(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_BUILD $*.CPP /Fo$*.obj
$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h
......@@ -30,7 +31,7 @@ gctest.exe: tests\test.obj gc.lib
# mapsympe -n -o gctest.sym gctest.exe
cord\de_win.rbj: cord\de_win.res
cvtres -$(CPU) cord\de_win.res -o cord\de_win.rbj
cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res
cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h
......
# generated automatically by aclocal 1.8.5 -*- Autoconf -*-
# generated automatically by aclocal 1.9 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
......@@ -33,14 +33,14 @@
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"])
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION so it can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.8.5])])
[AM_AUTOMAKE_VERSION([1.9])])
# AM_AUX_DIR_EXPAND
......@@ -108,7 +108,7 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -145,8 +145,8 @@ else
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.])
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# serial 7 -*- Autoconf -*-
......@@ -319,7 +319,8 @@ AC_SUBST([AMDEPBACKSLASH])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -355,27 +356,21 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
else
continue
fi
grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue
# Extract the definition of DEP_FILES from the Makefile without
# running `make'.
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n 's/^U = //p' < "$mf"`
test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
# We invoke sed twice because it is the simplest approach to
# changing $(DEPDIR) to its actual value in the expansion.
for file in `sed -n '
/^DEP_FILES = .*\\\\$/ {
s/^DEP_FILES = //
:loop
s/\\\\$//
p
n
/\\\\$/ b loop
p
}
/^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
......@@ -406,7 +401,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# This macro actually does too much some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
......@@ -482,7 +477,6 @@ AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AM_MISSING_PROG(AMTAR, tar)
AM_PROG_INSTALL_SH
AM_PROG_INSTALL_STRIP
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
......@@ -491,7 +485,9 @@ AC_REQUIRE([AM_PROG_MKDIR_P])dnl
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
......@@ -814,13 +810,21 @@ fi
# this.)
AC_DEFUN([AM_PROG_MKDIR_P],
[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
# Keeping the `.' argument allows $(mkdir_p) to be used without
# argument. Indeed, we sometimes output rules like
# We used to keeping the `.' as first argument, in order to
# allow $(mkdir_p) to be used without argument. As in
# $(mkdir_p) $(somedir)
# where $(somedir) is conditionally defined.
# (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more
# expensive solution, as it forces Make to start a sub-shell.)
mkdir_p='mkdir -p -- .'
# where $(somedir) is conditionally defined. However this is wrong
# for two reasons:
# 1. if the package is installed by a user who cannot write `.'
# make install will fail,
# 2. the above comment should most certainly read
# $(mkdir_p) $(DESTDIR)$(somedir)
# so it does not work when $(somedir) is undefined and
# $(DESTDIR) is not.
# To support the latter case, we have to write
# test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
# so the `.' trick is pointless.
mkdir_p='mkdir -p --'
else
# On NextStep and OpenStep, the `mkdir' command does not
# recognize any option. It will interpret all options as
......@@ -1055,4 +1059,112 @@ fi
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 1
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility.
AM_MISSING_PROG([AMTAR], [tar])
m4_if([$1], [v7],
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar;
do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([acinclude.m4])
......@@ -111,7 +111,7 @@ void GC_print_hblkfreelist()
for (i = 0; i <= N_HBLK_FLS; ++i) {
h = GC_hblkfreelist[i];
# ifdef USE_MUNMAP
if (0 != h) GC_printf1("Free list %ld (Total size %ld):\n",
if (0 != h) GC_printf1("Free list %ld:\n",
(unsigned long)i);
# else
if (0 != h) GC_printf2("Free list %ld (Total size %ld):\n",
......@@ -133,10 +133,12 @@ void GC_print_hblkfreelist()
h = hhdr -> hb_next;
}
}
if (total_free != GC_large_free_bytes) {
# ifndef USE_MUNMAP
if (total_free != GC_large_free_bytes) {
GC_printf1("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
(unsigned long) GC_large_free_bytes);
}
}
# endif
GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free);
}
......@@ -181,7 +183,7 @@ void GC_dump_regions()
hhdr = HDR(p);
GC_printf1("\t0x%lx ", (unsigned long)p);
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
GC_printf1("Missing header!!\n", hhdr);
GC_printf1("Missing header!!(%ld)\n", hhdr);
p += HBLKSIZE;
continue;
}
......@@ -375,9 +377,8 @@ void GC_unmap_old(void)
if (!IS_MAPPED(hhdr)) continue;
threshold = (unsigned short)(GC_gc_no - UNMAP_THRESHOLD);
last_rec = hhdr -> hb_last_reclaimed;
if (last_rec > GC_gc_no
|| last_rec < threshold && threshold < GC_gc_no
/* not recently wrapped */) {
if ((last_rec > GC_gc_no || last_rec < threshold)
&& threshold < GC_gc_no /* not recently wrapped */) {
sz = hhdr -> hb_sz;
GC_unmap((ptr_t)h, sz);
hhdr -> hb_flags |= WAS_UNMAPPED;
......@@ -422,6 +423,7 @@ void GC_merge_unmapped(void)
} else {
GC_remap((ptr_t)h, size);
hhdr -> hb_flags &= ~WAS_UNMAPPED;
hhdr -> hb_last_reclaimed = nexthdr -> hb_last_reclaimed;
}
} else {
/* Unmap any gap in the middle */
......@@ -468,7 +470,11 @@ int index;
if (total_size == bytes) return h;
rest = (struct hblk *)((word)h + bytes);
rest_hdr = GC_install_header(rest);
if (0 == rest_hdr) return(0);
if (0 == rest_hdr) {
/* This may be very bad news ... */
WARN("Header allocation failed: Dropping block.\n", 0);
return(0);
}
rest_hdr -> hb_sz = total_size - bytes;
rest_hdr -> hb_flags = 0;
# ifdef GC_ASSERTIONS
......@@ -784,6 +790,9 @@ signed_word size;
size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
GC_remove_counts(hbp, (word)size);
hhdr->hb_sz = size;
# ifdef USE_MUNMAP
hhdr -> hb_last_reclaimed = GC_gc_no;
# endif
/* Check for duplicate deallocation in the easy case */
if (HBLK_IS_FREE(hhdr)) {
......@@ -809,11 +818,17 @@ signed_word size;
if (IS_MAPPED(prevhdr)) {
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
prevhdr -> hb_sz += hhdr -> hb_sz;
# ifdef USE_MUNMAP
prevhdr -> hb_last_reclaimed = GC_gc_no;
# endif
GC_remove_header(hbp);
hbp = prev;
hhdr = prevhdr;
}
}
/* FIXME: It is not clear we really always want to do these merges */
/* with -DUSE_MUNMAP, since it updates ages and hence prevents */
/* unmapping. */
GC_large_free_bytes += size;
GC_add_to_fl(hbp, hhdr);
......
......@@ -133,7 +133,7 @@ int GC_n_attempts = 0; /* Number of attempts at finishing */
if (GC_print_stats) {
GC_printf0("Abandoning stopped marking after ");
GC_printf1("%lu msecs", (unsigned long)time_diff);
GC_printf1("(attempt %d)\n", (unsigned long) GC_n_attempts);
GC_printf1("(attempt %ld)\n", (unsigned long) GC_n_attempts);
}
# endif
return(1);
......@@ -228,10 +228,15 @@ void GC_clear_a_few_frames()
for (i = 0; i < NWORDS; i++) frames[i] = 0;
}
/* Heap size at which we need a collection to avoid expanding past */
/* limits used by blacklisting. */
static word GC_collect_at_heapsize = (word)(-1);
/* Have we allocated enough to amortize a collection? */
GC_bool GC_should_collect()
{
return(GC_adj_words_allocd() >= min_words_allocd());
return(GC_adj_words_allocd() >= min_words_allocd()
|| GC_heapsize >= GC_collect_at_heapsize);
}
......@@ -924,25 +929,37 @@ word n;
# endif
}
# endif
expansion_slop = 8 * WORDS_TO_BYTES(min_words_allocd());
if (5 * HBLKSIZE * MAXHINCR > expansion_slop) {
expansion_slop = 5 * HBLKSIZE * MAXHINCR;
}
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE;
if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
|| GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) {
/* Assume the heap is growing up */
GC_greatest_plausible_heap_addr =
GC_max(GC_greatest_plausible_heap_addr,
(ptr_t)space + bytes + expansion_slop);
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
(ptr_t)space + bytes + expansion_slop);
} else {
/* Heap is growing down */
GC_least_plausible_heap_addr =
GC_min(GC_least_plausible_heap_addr,
(ptr_t)space - expansion_slop);
(GC_PTR)GC_min((ptr_t)GC_least_plausible_heap_addr,
(ptr_t)space - expansion_slop);
}
# if defined(LARGE_CONFIG)
if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes
|| (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space)
&& GC_heapsize > 0) {
/* GC_add_to_heap will fix this, but ... */
WARN("Too close to address space limit: blacklisting ineffective\n", 0);
}
# endif
GC_prev_heap_addr = GC_last_heap_addr;
GC_last_heap_addr = (ptr_t)space;
GC_add_to_heap(space, bytes);
/* Force GC before we are likely to allocate past expansion_slop */
GC_collect_at_heapsize =
GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
# if defined(LARGE_CONFIG)
if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
GC_collect_at_heapsize = (word)(-1);
# endif
return(TRUE);
}
......
......@@ -13,14 +13,14 @@
/* Boehm, March 29, 1995 12:51 pm PST */
# ifdef CHECKSUMS
# include "gc_priv.h"
# include "private/gc_priv.h"
/* This is debugging code intended to verify the results of dirty bit */
/* computations. Works only in a single threaded environment. */
/* We assume that stubborn objects are changed only when they are */
/* enabled for writing. (Certain kinds of writing are actually */
/* safe under other conditions.) */
# define NSUMS 2000
# define NSUMS 10000
# define OFFSET 0x10000
......@@ -29,7 +29,7 @@ typedef struct {
word old_sum;
word new_sum;
struct hblk * block; /* Block to which this refers + OFFSET */
/* to hide it from colector. */
/* to hide it from collector. */
} page_entry;
page_entry GC_sums [NSUMS];
......@@ -76,12 +76,13 @@ int index;
{
page_entry *pe = GC_sums + index;
register hdr * hhdr = HDR(h);
struct hblk *b;
if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
pe -> old_sum = pe -> new_sum;
pe -> new_sum = GC_checksum(h);
# if !defined(MSWIN32) && !defined(MSWINCE)
if (pe -> new_sum != 0 && !GC_page_was_ever_dirty(h)) {
if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) {
GC_printf1("GC_page_was_ever_dirty(0x%lx) is wrong\n",
(unsigned long)h);
}
......@@ -91,13 +92,19 @@ int index;
} else {
GC_n_clean++;
}
if (pe -> new_valid && pe -> old_sum != pe -> new_sum) {
b = h;
while (IS_FORWARDING_ADDR_OR_NIL(hhdr) && hhdr != 0) {
b -= (word)hhdr;
hhdr = HDR(b);
}
if (pe -> new_valid
&& hhdr != 0 && hhdr -> hb_descr != 0 /* may contain pointers */
&& pe -> old_sum != pe -> new_sum) {
if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
/* Set breakpoint here */GC_n_dirty_errors++;
}
# ifdef STUBBORN_ALLOC
if (!IS_FORWARDING_ADDR_OR_NIL(hhdr)
&& hhdr -> hb_map != GC_invalid_map
if ( hhdr -> hb_map != GC_invalid_map
&& hhdr -> hb_obj_kind == STUBBORN
&& !GC_page_was_changed(h)
&& !GC_on_free_list(h)) {
......@@ -120,26 +127,17 @@ word dummy;
register hdr * hhdr = HDR(h);
register bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
bytes += HDR_BYTES + HBLKSIZE-1;
bytes += HBLKSIZE-1;
bytes &= ~(HBLKSIZE-1);
GC_bytes_in_used_blocks += bytes;
}
void GC_check_blocks()
{
word bytes_in_free_blocks = 0;
struct hblk * h = GC_hblkfreelist;
hdr * hhdr = HDR(h);
word sz;
word bytes_in_free_blocks = GC_large_free_bytes;
GC_bytes_in_used_blocks = 0;
GC_apply_to_all_blocks(GC_add_block, (word)0);
while (h != 0) {
sz = hhdr -> hb_sz;
bytes_in_free_blocks += sz;
h = hhdr -> hb_next;
hhdr = HDR(h);
}
GC_printf2("GC_bytes_in_used_blocks = %ld, bytes_in_free_blocks = %ld ",
GC_bytes_in_used_blocks, bytes_in_free_blocks);
GC_printf1("GC_heapsize = %ld\n", GC_heapsize);
......
......@@ -37,7 +37,7 @@ _GCC_TOPLEV_NONCANONICAL_TARGET
mkinstalldirs="`cd $ac_aux_dir && ${PWDCMD-pwd}`/mkinstalldirs"
AC_SUBST(mkinstalldirs)
AM_INIT_AUTOMAKE(gc, 6.1a1, no-define)
AM_INIT_AUTOMAKE(gc, 6.3, no-define)
# The autoconf 2.5x version of the no-executables hack.
sinclude(../config/no-executables.m4)
......@@ -79,7 +79,7 @@ case [$]{gc_basedir} in
*) gc_flagbasedir='[$](top_builddir)/'[$]{gc_basedir} ;;
esac
gc_cflags="[$]{gc_cflags} -I"'[$](top_builddir)'"/./targ-include -I[$]{gc_flagbasedir}/libc/include"
gc_cflags="[$]{gc_cflags} -Iinclude -I"'[$](top_builddir)'"/./targ-include -I[$]{gc_flagbasedir}/libc/include"
case "${host}" in
*-*-cygwin32*)
gc_cflags="[$]{gc_cflags} -I[$]{gc_flagbasedir}/../winsup/include"
......@@ -480,10 +480,7 @@ else
multilib_arg=
fi
AC_CONFIG_COMMANDS(boehm-cflags, [
dnl Put all the -I and -D options in a file.
echo "$AM_CPPFLAGS $DEFS" > boehm-cflags], [
DEFS="$DEFS"
AM_CPPFLAGS="$AM_CPPFLAGS"])
AC_CONFIG_HEADERS([include/gc_config.h])
AC_CONFIG_FILES(Makefile include/Makefile)
AC_OUTPUT
......@@ -261,7 +261,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
# ifdef __va_copy
__va_copy(vsprintf_args, args);
# else
# if defined(__GNUC__) /* and probably in other cases */
# if defined(__GNUC__) && !defined(__DJGPP__) /* and probably in other cases */
va_copy(vsprintf_args, args);
# else
vsprintf_args = args;
......
......@@ -11,6 +11,7 @@
* modified is included with the above copyright notice.
*/
/* Boehm, August 24, 1994 11:58 am PDT */
# include "gc.h" /* For GC_INIT() only */
# include "cord.h"
# include <string.h>
# include <stdio.h>
......@@ -116,7 +117,7 @@ void test_basics()
void test_extras()
{
# if defined(__OS2__)
# if defined(__OS2__) || defined(__DJGPP__)
# define FNAME1 "tmp1"
# define FNAME2 "tmp2"
# elif defined(AMIGA)
......@@ -162,6 +163,10 @@ void test_extras()
x = CORD_cat(x,x);
}
if ((f = fopen(FNAME2, "w")) == 0) ABORT("2nd open failed");
# ifdef __DJGPP__
/* FIXME: DJGPP workaround. Why does this help? */
if (fflush(f) != 0) ABORT("fflush failed");
# endif
if (CORD_put(x,f) == EOF) ABORT("CORD_put failed");
if (fclose(f) == EOF) ABORT("fclose failed");
w = CORD_from_file(f2 = fopen(FNAME2, "rb"));
......@@ -221,6 +226,7 @@ main()
# ifdef THINK_C
printf("cordtest:\n");
# endif
GC_INIT();
test_basics();
test_extras();
test_printf();
......
......@@ -385,9 +385,9 @@ size_t CORD_str(CORD x, size_t start, CORD s)
mask <<= 8;
mask |= 0xff;
s_buf <<= 8;
s_buf |= s_start[i];
s_buf |= (unsigned char)s_start[i];
x_buf <<= 8;
x_buf |= CORD_pos_fetch(xpos);
x_buf |= (unsigned char)CORD_pos_fetch(xpos);
CORD_next(xpos);
}
for (match_pos = start; ; match_pos++) {
......@@ -402,7 +402,7 @@ size_t CORD_str(CORD x, size_t start, CORD s)
return(CORD_NOT_FOUND);
}
x_buf <<= 8;
x_buf |= CORD_pos_fetch(xpos);
x_buf |= (unsigned char)CORD_pos_fetch(xpos);
CORD_next(xpos);
}
}
......
......@@ -569,9 +569,9 @@ char ** argv;
#if defined(MACINTOSH)
console_options.title = "\pDumb Editor";
cshow(stdout);
GC_init();
argc = ccommand(&argv);
#endif
GC_INIT();
if (argc != 2) goto usage;
arg_file_name = argv[1];
......
......@@ -2,7 +2,7 @@
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright (c) 1997 by Silicon Graphics. All rights reserved.
* Copyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved.
* Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
......@@ -195,13 +195,13 @@ ptr_t p;
(unsigned long)i);
switch(source) {
case GC_REFD_FROM_ROOT:
GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
GC_err_printf1("root at 0x%lx\n\n", (unsigned long)base);
goto out;
case GC_REFD_FROM_REG:
GC_err_printf0("root in register\n");
GC_err_printf0("root in register\n\n");
goto out;
case GC_FINALIZER_REFD:
GC_err_printf0("list of finalizable objects\n");
GC_err_printf0("list of finalizable objects\n\n");
goto out;
case GC_REFD_FROM_HEAP:
GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
......@@ -217,15 +217,20 @@ ptr_t p;
/* Force a garbage collection and generate a backtrace from a */
/* random heap address. */
void GC_generate_random_backtrace(void)
void GC_generate_random_backtrace_no_gc(void)
{
void * current;
GC_gcollect();
current = GC_generate_random_valid_address();
GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
GC_printf1("\n****Chose address 0x%lx in object\n", (unsigned long)current);
GC_print_backtrace(current);
}
void GC_generate_random_backtrace(void)
{
GC_gcollect();
GC_generate_random_backtrace_no_gc();
}
#endif /* KEEP_BACK_PTRS */
# define CROSSES_HBLK(p, sz) \
......@@ -325,6 +330,58 @@ register oh * ohdr;
}
#endif /* !SHORT_DBG_HDRS */
static GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = {0};
void GC_register_describe_type_fn(kind, fn)
int kind;
GC_describe_type_fn fn;
{
GC_describe_type_fns[kind] = fn;
}
/* Print a type description for the object whose client-visible address */
/* is p. */
void GC_print_type(p)
ptr_t p;
{
hdr * hhdr = GC_find_header(p);
char buffer[GC_TYPE_DESCR_LEN + 1];
int kind = hhdr -> hb_obj_kind;
if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) {
/* This should preclude free list objects except with */
/* thread-local allocation. */
buffer[GC_TYPE_DESCR_LEN] = 0;
(GC_describe_type_fns[kind])(p, buffer);
GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);
GC_err_puts(buffer);
} else {
switch(kind) {
case PTRFREE:
GC_err_puts("PTRFREE");
break;
case NORMAL:
GC_err_puts("NORMAL");
break;
case UNCOLLECTABLE:
GC_err_puts("UNCOLLECTABLE");
break;
# ifdef ATOMIC_UNCOLLECTABLE
case AUNCOLLECTABLE:
GC_err_puts("ATOMIC UNCOLLECTABLE");
break;
# endif
case STUBBORN:
GC_err_puts("STUBBORN");
break;
default:
GC_err_printf2("kind %ld, descr 0x%lx", kind, hhdr -> hb_descr);
}
}
}
void GC_print_obj(p)
ptr_t p;
{
......@@ -334,11 +391,13 @@ ptr_t p;
GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
GC_err_puts(ohdr -> oh_string);
# ifdef SHORT_DBG_HDRS
GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int));
GC_err_printf1(":%ld, ", (unsigned long)(ohdr -> oh_int));
# else
GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
GC_err_printf2(":%ld, sz=%ld, ", (unsigned long)(ohdr -> oh_int),
(unsigned long)(ohdr -> oh_sz));
# endif
GC_print_type((ptr_t)(ohdr + 1));
GC_err_puts(")\n");
PRINT_CALL_CHAIN(ohdr);
}
......@@ -403,6 +462,8 @@ void GC_start_debugging()
GC_register_displacement((word)sizeof(oh));
}
size_t GC_debug_header_size = sizeof(oh);
# if defined(__STDC__) || defined(__cplusplus)
void GC_debug_register_displacement(GC_word offset)
# else
......@@ -757,7 +818,15 @@ GC_PTR p;
uncollectable = TRUE;
}
# endif
if (uncollectable) GC_free(base);
if (uncollectable) {
GC_free(base);
} else {
size_t i;
size_t obj_sz = hhdr -> hb_sz - BYTES_TO_WORDS(sizeof(oh));
for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef;
GC_ASSERT((word *)p + i == (word *)base + hhdr -> hb_sz);
}
} /* !GC_find_leak */
}
......@@ -1013,7 +1082,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
if (0 == base) return;
if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer called with non-base-pointer 0x%lx\n",
obj);
......@@ -1045,7 +1115,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
if (0 == base) return;
if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
obj);
......@@ -1078,7 +1149,8 @@ GC_PTR *ocd;
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
if (0 == base) return;
if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
obj);
......
Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
The file linux_threads.c is also
Copyright (c) 1998 by Fergus Henderson. All rights reserved.
......@@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
This is version 6.3alpha1 of a conservative garbage collector for C and C++.
This is version 6.3 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
......
The garbage collector looks at a number of environment variables which are
then used to affect its operation. These are examined only on Un*x-like
platforms.
platforms and win32.
GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed up
process start-up.
......@@ -26,6 +26,14 @@ GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup
if you have a bug to report, but please include only the
last complete dump.
GC_BACKTRACES=<n> - Generate n random backtraces (for heap profiling) after
each GC. Collector must have been built with
KEEP_BACK_PTRS. This won't generate useful output unless
most objects in the heap were allocated through debug
allocators. This is intended to be only a statistical
sample; individual traces may be erroneous due to
concurrent heap mutation.
GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address
maps for the process, to stderr on every GC. Useful for
mapping root addresses to source for deciphering leak
......@@ -86,6 +94,28 @@ GC_RETRY_SIGNALS, GC_NO_RETRY_SIGNALS - Try to compensate for lost
was turned into a runtime flag to enable last-minute
work-arounds.
GC_IGNORE_FB[=<n>] - (Win32 only.) Try to avoid treating a mapped
frame buffer as part of the root set. Certain (higher end?)
graphics cards seems to result in the graphics memory mapped
into the user address space as writable memory.
Unfortunately, there seems to be no systematic way to
identify such memory. Setting the environment variable to n
causes the collector to ignore mappings longer than n MB.
The default value of n is currently 15. (This should cover
a 16 MB graphics card, since the mapping appears to be slightly
shorter than all of graphics memory. It will fail if a dll
writes pointers to collectable objects into a data segment
whose length is >= 15MB. Empirically that's rare, but
certainly possible.) WARNING: Security sensitive applications
should probably disable this feature by setting
GC_disallow_ignore_fb, or by building with -DNO_GETENV,
since small values could force collection of reachable
objects, which is conceivably a (difficult to exploit)
security hole. GC_IGNORE_FB values less than 3 MB
are never honored, eliminating this risk for most,
but not all, applications. This feature is likely to disappear
if/when we find a less disgusting "solution".
The following turn on runtime flags that are also program settable. Checked
only during initialization. We expect that they will usually be set through
other means, but this may help with debugging and testing:
......
......@@ -85,5 +85,10 @@ SRC_M3 Set if the collector is being built as a replacement of the
It's there primarily incase someone wants to port to a similar
system.
USE_COMPILER_TLS Assume the existence of __thread-style thread-local
storage. Set automatically for thread-local allocation with
the HP/UX vendor compiler. Usable with gcc on sufficiently
up-to-date ELF platforms.
The collector has at various times been compiled under Windows 95 & NT,
with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6, with
the GNU win32 environment, with Borland 4.5, with Watcom C, and recently
The collector has at various times been compiled under Windows 95 & later, NT,
and XP, with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6, with
the GNU win32 tools, with Borland 4.5, with Watcom C, and recently
with the Digital Mars compiler. It is likely that some of these have been
broken in the meantime. Patches are appreciated.
It runs under both win32s and win32, but with different semantics.
Under win32, all writable pages outside of the heaps and stack are
scanned for roots. Thus the collector sees pointers in DLL data
segments. Under win32s, only the main data segment is scanned.
(The main data segment should always be scanned. Under some
versions of win32s, other regions may also be scanned.)
Thus all accessible objects should be accessible from local variables
or variables in the main data segment. Alternatively, other data
segments (e.g. in DLLs) may be registered with the collector by
calling GC_init() and then GC_register_root_section(a), where
a is the address of some variable inside the data segment. (Duplicate
registrations are ignored, but not terribly quickly.)
(There are two reasons for this. We didn't want to see many 16:16
pointers. And the VirtualQuery call has different semantics under
the two systems, and under different versions of win32s.)
Win32 applications compiled with some flavor of gcc currently behave
like win32s applications, in that dynamic library data segments are
not scanned. (Gcc does not directly support Microsoft's "structured
exception handling". It turns out that use of this feature is
unavoidable if you scan arbitrary memory segments obtained from
VirtualQuery.)
The collector test program "gctest" is linked as a GUI application,
For historical reasons,
the collector test program "gctest" is linked as a GUI application,
but does not open any windows. Its output appears in the file
"gc.log". It may be started from the file manager. The hour glass
cursor may appear as long as it's running. If it is started from the
......@@ -60,11 +37,23 @@ This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan
Clark for tracking this down. There's some chance this may be fixed
in 6.1alpha4, since we now separate heap sections with an unused page.)
Microsoft Tools
---------------
For Microsoft development tools, rename NT_MAKEFILE as
MAKEFILE. (Make sure that the CPU environment variable is defined
to be i386.) In order to use the gc_cpp.h C++ interface, all
client code should include gc_cpp.h.
For historical reasons,
the collector test program "gctest" is linked as a GUI application,
but does not open any windows. Its output appears in the file
"gc.log". It may be started from the file manager. The hour glass
cursor may appear as long as it's running. If it is started from the
command line, it will usually run in the background. Wait a few
minutes (a few seconds on a modern machine) before you check the output.
You should see either a failure indication or a "Collector appears to
work" message.
If you would prefer a VC++.NET project file, ask boehm@acm.org. One has
been contributed, but it seems to contain some absolute paths etc., so
it can presumably only be a starting point, and is not in the standard
......@@ -75,13 +64,22 @@ Clients may need to define GC_NOT_DLL before including gc.h, if the
collector was built as a static library (as it normally is in the
absence of thread support).
GNU Tools
---------
For GNU-win32, use the regular makefile, possibly after uncommenting
the line "include Makefile.DLLs". The latter should be necessary only
if you want to package the collector as a DLL. The GNU-win32 port is
if you want to package the collector as a DLL.
[Is the following sentence obsolete? -HB] The GNU-win32 port is
believed to work only for b18, not b19, probably due to linker changes
in b19. This is probably fixable with a different definition of
DATASTART and DATAEND in gcconfig.h.
The collector should also be buildable under Cygwin with either the
old standard Makefile, or with the "configure;make" machinery.
Borland Tools
-------------
[Rarely tested.]
For Borland tools, use BCC_MAKEFILE. Note that
Borland's compiler defaults to 1 byte alignment in structures (-a1),
whereas Visual C++ appears to default to 8 byte alignment (/Zp8).
......@@ -97,6 +95,8 @@ version, change the line near the top. By default, it does not
require the assembler. If you do have the assembler, I recommend
removing the -DUSE_GENERIC.
Incremental Collection
----------------------
There is some support for incremental collection. This is
currently pretty simple-minded. Pages are protected. Protection
faults are caught by a handler installed at the bottom of the handler
......@@ -112,7 +112,11 @@ is called.)
Note that incremental collection is disabled with -DSMALL_CONFIG.
James Clark has contributed the necessary code to support win32 threads.
Threads
-------
James Clark has contributed the necessary code to support win32 threads
with the collector in a DLL.
Use NT_THREADS_MAKEFILE (a.k.a gc.mak) instead of NT_MAKEFILE
to build this version. Note that this requires some files whose names
are more than 8 + 3 characters long. Thus you should unpack the tar file
......@@ -128,12 +132,31 @@ This version relies on the collector residing in a dll.
This version currently supports incremental collection only if it is
enabled before any additional threads are created.
Version 4.13 attempts to fix some of the earlier problems, but there
may be other issues. If you need solid support for win32 threads, you
might check with Geodesic Systems. Their collector must be licensed,
but they have invested far more time in win32-specific issues.
Hans
Since 6.3alpha2, threads are also better supported in static library builds
with Microsoft tools (use NT_STATIC_THREADS_MAKEFILE) and with the GNU
tools. In all cases,the collector must be built with GC_WIN32_THREADS
defined, even if the Cygwin pthreads interface is used.
(NT_STATIC_THREADS_MAKEFILE does this implicitly. Under Cygwin,
./configure --enable-threads=posix defines GC_WIN32_THREADS.) Threads must be
created with GC_CreateThread. This can be accomplished by
including gc.h and then calling CreateThread, which is redefined
by gc.h.
For the statically linked versions, it is required that GC_init()
be called before other GC calls, since there seems to be no implicit way
to initialize the allocation lock. The easiest way to ensure this in
portable code is to call GC_INIT() from the main executable (not
a dynamic library) before calling any other GC_ routines.
We strongly advise against using the TerminateThread() win32 API call,
especially with the garbage collector. Any use is likely to provoke a
crash in the GC, since it makes it impossible for the collector to
correctly track threads.
Watcom compiler
---------------
Ivan V. Demakov's README for the Watcom port:
......@@ -167,4 +190,26 @@ important, otherwise resulting programs will not run.
Ivan Demakov (email: ivan@tgrad.nsk.su)
Win32S
------
[The following is probably obsolete. The win32s support is still in the
collector, but I doubt anyone cares, or has tested it recently.]
The collector runs under both win32s and win32, but with different semantics.
Under win32, all writable pages outside of the heaps and stack are
scanned for roots. Thus the collector sees pointers in DLL data
segments. Under win32s, only the main data segment is scanned.
(The main data segment should always be scanned. Under some
versions of win32s, other regions may also be scanned.)
Thus all accessible objects should be accessible from local variables
or variables in the main data segment. Alternatively, other data
segments (e.g. in DLLs) may be registered with the collector by
calling GC_init() and then GC_register_root_section(a), where
a is the address of some variable inside the data segment. (Duplicate
registrations are ignored, but not terribly quickly.)
(There are two reasons for this. We didn't want to see many 16:16
pointers. And the VirtualQuery call has different semantics under
the two systems, and under different versions of win32s.)
......@@ -47,6 +47,10 @@ The garbage collector generates warning messages of the form
<PRE>
Needed to allocate blacklisted block at 0x...
</pre>
or
<PRE>
Repeated allocation of very large block ...
</pre>
when it needs to allocate a block at a location that it knows to be
referenced by a false pointer. These false pointers can be either permanent
(<I>e.g.</i> a static integer variable that never changes) or temporary.
......@@ -123,7 +127,8 @@ is commonly caused by data structures that are no longer being used,
but were not cleared, or by caches growing without bounds.
<LI> Pointer misidentification. The garbage collector is interpreting
integers or other data as pointers and retaining the "referenced"
objects.
objects. A common symptom is that GC_dump() shows much of the heap
as black-listed.
<LI> Heap fragmentation. This should never result in unbounded growth,
but it may account for larger heaps. This is most commonly caused
by allocation of large objects. On some platforms it can be reduced
......@@ -180,6 +185,12 @@ primitives is <TT>gc_typed.h</tt>, or separate out the pointerfree component.
<LI> Consider using <TT>GC_malloc_ignore_off_page()</tt>
to allocate large objects. (See <TT>gc.h</tt> and above for details.
Large means &gt; 100K in most environments.)
<LI> If your heap size is larger than 100MB or so, build the collector with
-DLARGE_CONFIG. This allows the collector to keep more precise black-list
information.
<LI> If you are using heaps close to, or larger than, a gigabyte on a 32-bit
machine, you may want to consider moving to a platform with 64-bit pointers.
This is very likely to resolve any false pointer issues.
</ol>
<H2>Prematurely Reclaimed Objects</h2>
The usual symptom of this is a segmentation fault, or an obviously overwritten
......
.TH GC_MALLOC 1L "12 February 1996"
.TH GC_MALLOC 1L "2 October 2003"
.SH NAME
GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental, GC_register_finalizer, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_warn_proc \- Garbage collecting malloc replacement
.SH SYNOPSIS
#include "gc.h"
.br
# define malloc(n) GC_malloc(n)
void * GC_malloc(size_t size);
.br
... malloc(...) ...
void GC_free(void *ptr);
.br
void * GC_realloc(void *ptr, size_t size);
.br
.sp
cc ... gc.a
......@@ -23,6 +25,11 @@ will attempt to reclaim inaccessible space automatically by invoking a conservat
GC_malloc
or friends.
.LP
In most cases it is preferable to call the macros GC_MALLOC, GC_FREE, etc.
instead of calling GC_malloc and friends directly. This allows debugging
versions of the routines to be substituted by defining GC_DEBUG before
including gc.h.
.LP
See the documentation in the include file gc_cpp.h for an alternate, C++ specific interface to the garbage collector.
.LP
Unlike the standard implementations of malloc,
......@@ -56,9 +63,16 @@ It is also possible to use the collector to find storage leaks in programs desti
.LP
The collector may, on rare occasion produce warning messages. On UNIX machines these appear on stderr. Warning messages can be filtered, redirected, or ignored with
.I
GC_set_warn_proc.
GC_set_warn_proc
This is recommended for production code. See gc.h for details.
.LP
Fully portable code should call
.I
GC_INIT
from the main program before making any other GC calls.
On most platforms this does nothing and the collector is initialized on first use.
On a few platforms explicit initialization is necessary. And it can never hurt.
.LP
Debugging versions of many of the above routines are provided as macros. Their names are identical to the above, but consist of all capital letters. If GC_DEBUG is defined before gc.h is included, these routines do additional checking, and allow the leak detecting version of the collector to produce slightly more useful output. Without GC_DEBUG defined, they behave exactly like the lower-case versions.
.LP
On some machines, collection will be performed incrementally after a call to
......@@ -71,10 +85,13 @@ Other facilities not discussed here include limited facilities to support increm
.SH "SEE ALSO"
The README and gc.h files in the distribution. More detailed definitions of the functions exported by the collector are given there. (The above list is not complete.)
.LP
The web site at http://www.hpl.hp.com/personal/Hans_Boehm/gc .
.LP
Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment",
\fISoftware Practice & Experience\fP, September 1988, pp. 807-820.
.LP
The malloc(3) man page.
.LP
.SH AUTHOR
Hans-J. Boehm (boehm@parc.xerox.com). Some of the code was written by others, most notably Alan Demers.
Hans-J. Boehm (Hans.Boehm@hp.com).
Some of the code was written by others, most notably Alan Demers.
......@@ -4,7 +4,7 @@
<AUTHOR> Hans-J. Boehm, HP Labs (Much of this was written at SGI)</author>
</HEAD>
<BODY>
<H1> <I>This is under construction</i> </h1>
<H1> <I>This is under construction, and may always be.</i> </h1>
<H1> Conservative GC Algorithmic Overview </h1>
<P>
This is a description of the algorithms and data structures used in our
......@@ -27,20 +27,22 @@ We assume the default finalization model, but the code affected by that
is very localized.
<H2> Introduction </h2>
The garbage collector uses a modified mark-sweep algorithm. Conceptually
it operates roughly in four phases:
it operates roughly in four phases, which are performed occasionally
as part of a memory allocation:
<OL>
<LI>
<I>Preparation</i> Clear all mark bits, indicating that all objects
<I>Preparation</i> Each object has an associated mark bit.
Clear all mark bits, indicating that all objects
are potentially unreachable.
<LI>
<I>Mark phase</i> Marks all objects that can be reachable via chains of
pointers from variables. Normally the collector has no real information
pointers from variables. Often the collector has no real information
about the location of pointer variables in the heap, so it
views all static data areas, stacks and registers as potentially containing
containing pointers. Any bit patterns that represent addresses inside
pointers. Any bit patterns that represent addresses inside
heap objects managed by the collector are viewed as pointers.
Unless the client program has made heap object layout information
available to the collector, any heap objects found to be reachable from
......@@ -87,8 +89,12 @@ others are not. Some may have per-object type descriptors that
determine pointer locations. Or a specific kind may correspond
to one specific object layout. Two built-in kinds are uncollectable.
One (<TT>STUBBORN</tt>) is immutable without special precautions.
In spite of that, it is very likely that most applications currently
In spite of that, it is very likely that most C clients of the
collector currently
use at most two kinds: <TT>NORMAL</tt> and <TT>PTRFREE</tt> objects.
The <A HREF="http://gcc.gnu.org/java">gcj</a> runtime also makes
heavy use of a kind (allocated with GC_gcj_malloc) that stores
type information at a known offset in method tables.
<P>
The collector uses a two level allocator. A large block is defined to
be one larger than half of <TT>HBLKSIZE</tt>, which is a power of 2,
......@@ -175,6 +181,32 @@ for a single pool of physical memory.
<H2>Mark phase</h2>
At each collection, the collector marks all objects that are
possibly reachable from pointer variables. Since it cannot generally
tell where pointer variables are located, it scans the following
<I>root segments</i> for pointers:
<UL>
<LI>The registers. Depending on the architecture, this may be done using
assembly code, or by calling a <TT>setjmp</tt>-like function which saves
register contents on the stack.
<LI>The stack(s). In the case of a single-threaded application,
on most platforms this
is done by scanning the memory between (an approximation of) the current
stack pointer and <TT>GC_stackbottom</tt>. (For Itanium, the register stack
scanned separately.) The <TT>GC_stackbottom</tt> variable is set in
a highly platform-specific way depending on the appropriate configuration
information in <TT>gcconfig.h</tt>. Note that the currently active
stack needs to be scanned carefully, since callee-save registers of
client code may appear inside collector stack frames, which may
change during the mark process. This is addressed by scanning
some sections of the stack "eagerly", effectively capturing a snapshot
at one point in time.
<LI>Static data region(s). In the simplest case, this is the region
between <TT>DATASTART</tt> and <TT>DATAEND</tt>, as defined in
<TT>gcconfig.h</tt>. However, in most cases, this will also involve
static data regions associated with dynamic libraries. These are
identified by the mostly platform-specific code in <TT>dyn_load.c</tt>.
</ul>
The marker maintains an explicit stack of memory regions that are known
to be accessible, but that have not yet been searched for contained pointers.
Each stack entry contains the starting address of the block to be scanned,
......@@ -182,8 +214,11 @@ as well as a descriptor of the block. If no layout information is
available for the block, then the descriptor is simply a length.
(For other possibilities, see <TT>gc_mark.h</tt>.)
<P>
At the beginning of the mark phase, all root segments are pushed on the
stack by <TT>GC_push_roots</tt>. If <TT>ALL_INTERIOR_PTRS</tt> is not
At the beginning of the mark phase, all root segments
(as described above) are pushed on the
stack by <TT>GC_push_roots</tt>. (Registers and eagerly processed
stack sections are processed by pushing the referenced objects instead
of the stack section itself.) If <TT>ALL_INTERIOR_PTRS</tt> is not
defined, then stack roots require special treatment. In this case, the
normal marking code ignores interior pointers, but <TT>GC_push_all_stack</tt>
explicitly checks for interior pointers and pushes descriptors for target
......@@ -479,8 +514,9 @@ if there is low demand for small pointerfree objects.
We support several different threading models. Unfortunately Pthreads,
the only reasonably well standardized thread model, supports too narrow
an interface for conservative garbage collection. There appears to be
no completely portable way to allow the collector to coexist with various Pthreads
implementations. Hence we currently support only a few of the more
no completely portable way to allow the collector
to coexist with various Pthreads
implementations. Hence we currently support only the more
common Pthreads implementations.
<P>
In particular, it is very difficult for the collector to stop all other
......@@ -510,6 +546,10 @@ accomplished with <TT># define</tt>'s in <TT>gc.h</tt>
(really <TT>gc_pthread_redirects.h</tt>), or optionally
by using ld's function call wrapping mechanism under Linux.
<P>
Recent versions of the collector support several facilites to enhance
the processor-scalability and thread performance of the collector.
These are discussed in more detail <A HREF="scale.html">here</a>.
<P>
Comments are appreciated. Please send mail to
<A HREF="mailto:boehm@acm.org"><TT>boehm@acm.org</tt></a> or
<A HREF="mailto:Hans.Boehm@hp.com"><TT>Hans.Boehm@hp.com</tt></a>
......
......@@ -91,10 +91,18 @@
/* Newer versions of GNU/Linux define this macro. We
* define it similarly for any ELF systems that don't. */
# ifndef ElfW
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
# define ElfW(type) Elf32_##type
# ifdef __NetBSD__
# if ELFSIZE == 32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
# endif
# else
# define ElfW(type) Elf64_##type
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
# endif
# endif
# endif
......@@ -552,6 +560,7 @@ extern void * GC_roots_present();
/* The type is a lie, since the real type doesn't make sense here, */
/* and we only test for NULL. */
/* We use /proc to track down all parts of the address space that are */
/* mapped by the process, and throw out regions we know we shouldn't */
/* worry about. This may also work under other SVR4 variants. */
......@@ -726,6 +735,90 @@ void GC_register_dynamic_libraries()
# define HAVE_REGISTER_MAIN_STATIC_DATA
GC_bool GC_warn_fb = TRUE; /* Warn about traced likely */
/* graphics memory. */
GC_bool GC_disallow_ignore_fb = FALSE;
int GC_ignore_fb_mb; /* Ignore mappings bigger than the */
/* specified number of MB. */
GC_bool GC_ignore_fb = FALSE; /* Enable frame buffer */
/* checking. */
/* Issue warning if tracing apparent framebuffer. */
/* This limits us to one warning, and it's a back door to */
/* disable that. */
/* Should [start, start+len) be treated as a frame buffer */
/* and ignored? */
/* Unfortunately, we currently have no real way to tell */
/* automatically, and rely largely on user input. */
/* FIXME: If we had more data on this phenomenon (e.g. */
/* is start aligned to a MB multiple?) we should be able to */
/* do better. */
/* Based on a very limited sample, it appears that: */
/* - Frame buffer mappings appear as mappings of length */
/* 2**n MB - 192K. (We guess the 192K can vary a bit.) */
/* - Have a stating address at best 64K aligned. */
/* I'd love more information about the mapping, since I */
/* can't reproduce the problem. */
static GC_bool is_frame_buffer(ptr_t start, size_t len)
{
static GC_bool initialized = FALSE;
# define MB (1024*1024)
# define DEFAULT_FB_MB 15
# define MIN_FB_MB 3
if (GC_disallow_ignore_fb) return FALSE;
if (!initialized) {
char * ignore_fb_string = GETENV("GC_IGNORE_FB");
if (0 != ignore_fb_string) {
while (*ignore_fb_string == ' ' || *ignore_fb_string == '\t')
++ignore_fb_string;
if (*ignore_fb_string == '\0') {
GC_ignore_fb_mb = DEFAULT_FB_MB;
} else {
GC_ignore_fb_mb = atoi(ignore_fb_string);
if (GC_ignore_fb_mb < MIN_FB_MB) {
WARN("Bad GC_IGNORE_FB value. Using %ld\n", DEFAULT_FB_MB);
GC_ignore_fb_mb = DEFAULT_FB_MB;
}
}
GC_ignore_fb = TRUE;
} else {
GC_ignore_fb_mb = DEFAULT_FB_MB; /* For warning */
}
initialized = TRUE;
}
if (len >= ((size_t)GC_ignore_fb_mb << 20)) {
if (GC_ignore_fb) {
return TRUE;
} else {
if (GC_warn_fb) {
WARN("Possible frame buffer mapping at 0x%lx: \n"
"\tConsider setting GC_IGNORE_FB to improve performance.\n",
start);
GC_warn_fb = FALSE;
}
return FALSE;
}
} else {
return FALSE;
}
}
# ifdef DEBUG_VIRTUALQUERY
void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
{
GC_printf4("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
buf -> BaseAddress, buf -> AllocationBase, buf -> RegionSize,
buf -> RegionSize);
GC_printf4("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
"Type = %lx\n",
buf -> AllocationProtect, buf -> State, buf -> Protect,
buf -> Type);
}
# endif /* DEBUG_VIRTUALQUERY */
void GC_register_dynamic_libraries()
{
MEMORY_BASIC_INFORMATION buf;
......@@ -762,7 +855,11 @@ void GC_register_dynamic_libraries()
if (buf.State == MEM_COMMIT
&& (protect == PAGE_EXECUTE_READWRITE
|| protect == PAGE_READWRITE)
&& !GC_is_heap_base(buf.AllocationBase)) {
&& !GC_is_heap_base(buf.AllocationBase)
&& !is_frame_buffer(p, buf.RegionSize)) {
# ifdef DEBUG_VIRTUALQUERY
GC_dump_meminfo(&buf);
# endif
if ((char *)p != limit) {
GC_cond_add_roots(base, limit);
base = p;
......@@ -980,12 +1077,13 @@ void GC_register_dynamic_libraries()
#ifdef DARWIN
/* __private_extern__ hack required for pre-3.4 gcc versions. */
#ifndef __private_extern__
#define __private_extern__ extern
#include <mach-o/dyld.h>
#undef __private_extern__
# define __private_extern__ extern
# include <mach-o/dyld.h>
# undef __private_extern__
#else
#include <mach-o/dyld.h>
# include <mach-o/dyld.h>
#endif
#include <mach-o/getsect.h>
......
......@@ -807,8 +807,37 @@ void (* GC_finalizer_notifier)() = (void (*) GC_PROTO((void)))0;
static GC_word last_finalizer_notification = 0;
#ifdef KEEP_BACK_PTRS
void GC_generate_random_backtrace_no_gc(void);
#endif
void GC_notify_or_invoke_finalizers GC_PROTO((void))
{
/* This is a convenient place to generate backtraces if appropriate, */
/* since that code is not callable with the allocation lock. */
# ifdef KEEP_BACK_PTRS
if (GC_backtraces > 0) {
static word last_back_trace_gc_no = 3; /* Skip early ones. */
long i;
LOCK();
if (GC_gc_no > last_back_trace_gc_no) {
/* Stops when GC_gc_no wraps; that's OK. */
last_back_trace_gc_no = (word)(-1); /* disable others. */
for (i = 0; i < GC_backtraces; ++i) {
/* FIXME: This tolerates concurrent heap mutation, */
/* which may cause occasional mysterious results. */
/* We need to release the GC lock, since GC_print_callers */
/* acquires it. It probably shouldn't. */
UNLOCK();
GC_generate_random_backtrace_no_gc();
LOCK();
}
last_back_trace_gc_no = GC_gc_no;
}
UNLOCK();
}
# endif
if (GC_finalize_now == 0) return;
if (!GC_finalize_on_demand) {
(void) GC_invoke_finalizers();
......
......@@ -14,8 +14,6 @@
*/
/* Boehm, July 31, 1995 5:02 pm PDT */
#ifdef GC_GCJ_SUPPORT
/*
* This is an allocator interface tuned for gcj (the GNU static
* java compiler).
......@@ -40,6 +38,8 @@
#include "gc_gcj.h"
#include "private/dbg_mlc.h"
#ifdef GC_GCJ_SUPPORT
GC_bool GC_gcj_malloc_initialized = FALSE;
int GC_gcj_kind; /* Object kind for objects with descriptors */
......@@ -72,46 +72,36 @@ void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
GC_printf0("Gcj-style type information is disabled!\n");
}
# endif
GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
GC_mark_procs[mp_index] = (GC_mark_proc)mp;
if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
/* Set up object kind gcj-style indirect descriptor. */
GC_gcjobjfreelist = (ptr_t *)
GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (GC_gcjobjfreelist == 0) ABORT("Couldn't allocate GC_gcjobjfreelist");
BZERO(GC_gcjobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
GC_gcj_kind = GC_n_kinds++;
GC_obj_kinds[GC_gcj_kind].ok_freelist = GC_gcjobjfreelist;
GC_obj_kinds[GC_gcj_kind].ok_reclaim_list = 0;
GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
if (ignore_gcj_info) {
/* Use a simple length-based descriptor, thus forcing a fully */
/* conservative scan. */
GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
(0 | GC_DS_LENGTH),
TRUE, TRUE);
} else {
GC_obj_kinds[GC_gcj_kind].ok_descriptor =
(((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
| GC_DS_PER_OBJECT);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = FALSE;
GC_gcj_kind = GC_new_kind_inner(
(void **)GC_gcjobjfreelist,
(((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
| GC_DS_PER_OBJECT),
FALSE, TRUE);
}
GC_obj_kinds[GC_gcj_kind].ok_init = TRUE;
/* Set up object kind for objects that require mark proc call. */
GC_gcjdebugobjfreelist = (ptr_t *)
GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (GC_gcjdebugobjfreelist == 0)
ABORT("Couldn't allocate GC_gcjdebugobjfreelist");
BZERO(GC_gcjdebugobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
GC_gcj_debug_kind = GC_n_kinds++;
GC_obj_kinds[GC_gcj_debug_kind].ok_freelist = GC_gcjdebugobjfreelist;
GC_obj_kinds[GC_gcj_debug_kind].ok_reclaim_list = 0;
if (ignore_gcj_info) {
GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
GC_gcj_debug_kind = GC_gcj_kind;
GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
} else {
GC_obj_kinds[GC_gcj_debug_kind].ok_descriptor =
GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */);
GC_obj_kinds[GC_gcj_debug_kind].ok_relocate_descr = FALSE;
GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
GC_gcj_debug_kind = GC_new_kind_inner(
(void **)GC_gcjdebugobjfreelist,
GC_MAKE_PROC(mp_index,
1 /* allocated with debug info */),
FALSE, TRUE);
}
GC_obj_kinds[GC_gcj_debug_kind].ok_init = TRUE;
UNLOCK();
ENABLE_SIGNALS();
}
......@@ -124,6 +114,25 @@ ptr_t GC_clear_stack();
#define GENERAL_MALLOC_IOP(lb,k) \
(GC_PTR)GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
/* We need a mechanism to release the lock and invoke finalizers. */
/* We don't really have an opportunity to do this on a rarely executed */
/* path on which the lock is not held. Thus we check at a */
/* rarely executed point at which it is safe to release the lock. */
/* We do this even where we could just call GC_INVOKE_FINALIZERS, */
/* since it's probably cheaper and certainly more uniform. */
/* FIXME - Consider doing the same elsewhere? */
static void maybe_finalize()
{
static int last_finalized_no = 0;
if (GC_gc_no == last_finalized_no) return;
if (!GC_is_initialized) return;
UNLOCK();
GC_INVOKE_FINALIZERS();
last_finalized_no = GC_gc_no;
LOCK();
}
/* Allocate an object, clear it, and store the pointer to the */
/* type structure (vtable in gcj). */
/* This adds a byte at the end of the object if GC_malloc would.*/
......@@ -143,7 +152,8 @@ DCL_LOCK_STATE;
opp = &(GC_gcjobjfreelist[lw]);
LOCK();
op = *opp;
if( EXPECT(op == 0, 0)) {
if(EXPECT(op == 0, 0)) {
maybe_finalize();
op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
if (0 == op) {
UNLOCK();
......@@ -161,6 +171,7 @@ DCL_LOCK_STATE;
UNLOCK();
} else {
LOCK();
maybe_finalize();
op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
if (0 == op) {
UNLOCK();
......@@ -179,10 +190,10 @@ GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
{
GC_PTR result;
/* We clone the code from GC_debug_gcj_malloc, so that we */
/* dont end up with extra frames on the stack, which could */
/* We're careful to avoid extra calls, which could */
/* confuse the backtrace. */
LOCK();
maybe_finalize();
result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
if (result == 0) {
UNLOCK();
......@@ -215,6 +226,7 @@ DCL_LOCK_STATE;
LOCK();
op = *opp;
if( EXPECT(op == 0, 0) ) {
maybe_finalize();
op = (ptr_t)GC_clear_stack(
GC_generic_malloc_words_small_inner(lw, GC_gcj_kind));
if (0 == op) {
......@@ -242,6 +254,7 @@ void * GC_debug_gcj_fast_malloc(size_t lw,
/* dont end up with extra frames on the stack, which could */
/* confuse the backtrace. */
LOCK();
maybe_finalize();
result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
if (result == 0) {
UNLOCK();
......@@ -278,6 +291,7 @@ DCL_LOCK_STATE;
opp = &(GC_gcjobjfreelist[lw]);
LOCK();
if( (op = *opp) == 0 ) {
maybe_finalize();
op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
# ifdef MERGE_SIZES
lw = GC_size_map[lb]; /* May have been uninitialized. */
......@@ -289,6 +303,8 @@ DCL_LOCK_STATE;
*(void **)op = ptr_to_struct_containing_descr;
UNLOCK();
} else {
LOCK();
maybe_finalize();
op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
if (0 != op) {
*(void **)op = ptr_to_struct_containing_descr;
......
......@@ -206,7 +206,7 @@ register struct hblk * h;
{
hdr * result;
if (!get_index((word) h)) return(FALSE);
if (!get_index((word) h)) return(0);
result = alloc_hdr();
SET_HDR(h, result);
# ifdef USE_MUNMAP
......
......@@ -4,6 +4,9 @@
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
#ifdef __DJGPP__
#include <dirent.h>
#endif /* __DJGPP__ */
int main(argc, argv, envp)
int argc;
......@@ -11,12 +14,21 @@ char ** argv;
char ** envp;
{
FILE * f;
#ifdef __DJGPP__
DIR * d;
#endif /* __DJGPP__ */
if (argc < 3) goto Usage;
if ((f = fopen(argv[1], "rb")) != 0
|| (f = fopen(argv[1], "r")) != 0) {
fclose(f);
return(0);
}
#ifdef __DJGPP__
if ((d = opendir(argv[1])) != 0) {
closedir(d);
return(0);
}
#endif
printf("^^^^Starting command^^^^\n");
fflush(stdout);
execvp(argv[2], argv+2);
......
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.9 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
......@@ -135,6 +135,8 @@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
......@@ -318,7 +320,7 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
......
......@@ -30,6 +30,7 @@
# define _GC_H
# include <gc_config.h>
# include "gc_config_macros.h"
# if defined(__STDC__) || defined(__cplusplus)
......@@ -52,11 +53,18 @@
/* even semi-portably. The following is probably no better/worse */
/* than almost anything else. */
/* The ANSI standard suggests that size_t and ptr_diff_t might be */
/* better choices. But those appear to have incorrect definitions */
/* on may systems. Notably "typedef int size_t" seems to be both */
/* frequent and WRONG. */
typedef unsigned long GC_word;
typedef long GC_signed_word;
/* better choices. But those had incorrect definitions on some older */
/* systems. Notably "typedef int size_t" is WRONG. */
#ifndef _WIN64
typedef unsigned long GC_word;
typedef long GC_signed_word;
#else
/* Win64 isn't really supported yet, but this is the first step. And */
/* it might cause error messages to show up in more plausible places. */
/* This needs basetsd.h, which is included by windows.h. */
typedef ULONG_PTR GC_word;
typedef LONG_PTR GC_word;
#endif
/* Public read-only variables */
......@@ -247,6 +255,7 @@ GC_API unsigned long GC_time_limit;
* allocation, since unlike the regular allocation routines, GC_local_malloc
* is not self-initializing. If you use GC_local_malloc you should arrange
* to call this somehow (e.g. from a constructor) before doing any allocation.
* For win32 threads, it needs to be called explicitly.
*/
GC_API void GC_init GC_PROTO((void));
......@@ -470,14 +479,19 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
# include <features.h>
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
&& !defined(__ia64__)
# define GC_HAVE_BUILTIN_BACKTRACE
# define GC_CAN_SAVE_CALL_STACKS
# ifndef GC_HAVE_BUILTIN_BACKTRACE
# define GC_HAVE_BUILTIN_BACKTRACE
# endif
# endif
# if defined(__i386__) || defined(__x86_64__)
# define GC_CAN_SAVE_CALL_STACKS
# endif
#endif
#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS)
# define GC_CAN_SAVE_CALL_STACKS
#endif
#if defined(__sparc__)
# define GC_CAN_SAVE_CALL_STACKS
#endif
......@@ -604,7 +618,7 @@ GC_API GC_PTR GC_debug_realloc_replacement
/* Finalization. Some of these primitives are grossly unsafe. */
/* The idea is to make them both cheap, and sufficient to build */
/* a safer layer, closer to PCedar finalization. */
/* a safer layer, closer to Modula-3, Java, or PCedar finalization. */
/* The interface represents my conclusions from a long discussion */
/* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes, */
/* Christian Jacobi, and Russ Atkinson. It's not perfect, and */
......@@ -774,6 +788,7 @@ GC_API GC_PTR GC_call_with_alloc_lock
/* The following routines are primarily intended for use with a */
/* preprocessor which inserts calls to check C pointer arithmetic. */
/* They indicate failure by invoking the corresponding _print_proc. */
/* Check that p and q point to the same object. */
/* Fail conspicuously if they don't. */
......@@ -851,7 +866,7 @@ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p));
# define GC_PTR_STORE(p, q) *((p) = (q))
#endif
/* Fynctions called to report pointer checking errors */
/* Functions called to report pointer checking errors */
GC_API void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR p, GC_PTR q));
GC_API void (*GC_is_valid_displacement_print_proc)
......@@ -919,13 +934,19 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
#endif /* defined(GC_WIN32_THREADS) && !cygwin */
/*
* If you are planning on putting
* the collector in a SunOS 5 dynamic library, you need to call GC_INIT()
* from the statically loaded program section.
* This circumvents a Solaris 2.X (X<=4) linker bug.
*/
#if defined(sparc) || defined(__sparc)
/*
* Fully portable code should call GC_INIT() from the main program
* before making any other GC_ calls. On most platforms this is a
* no-op and the collector self-initializes. But a number of platforms
* make that too hard.
*/
#if (defined(sparc) || defined(__sparc)) && defined(sun)
/*
* If you are planning on putting
* the collector in a SunOS 5 dynamic library, you need to call GC_INIT()
* from the statically loaded program section.
* This circumvents a Solaris 2.X (X<=4) linker bug.
*/
# define GC_INIT() { extern end, etext; \
GC_noop(&end, &etext); }
#else
......@@ -936,13 +957,13 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
*/
# define GC_INIT() { GC_add_roots(DATASTART, DATAEND); }
# else
# if defined(__APPLE__) && defined(__MACH__)
# if defined(__APPLE__) && defined(__MACH__) || defined(GC_WIN32_THREADS)
# define GC_INIT() { GC_init(); }
# else
# define GC_INIT()
# endif
# endif
#endif
# endif /* !__MACH && !GC_WIN32_THREADS */
# endif /* !AIX && !cygwin */
#endif /* !sparc */
#if !defined(_WIN32_WCE) \
&& ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
......
#undef ALL_INTERIOR_POINTERS
#undef ATOMIC_UNCOLLECTABLE
#undef DATASTART_IS_ETEXT
#undef DBG_HDRS_ALL
#undef DGUX_THREADS
#undef ECOS
#undef GC_AIX_THREADS
#undef GC_DARWIN_THREADS
#undef GC_DGUX386_THREADS
#undef GC_FREEBSD_THREADS
#undef GC_GCJ_SUPPORT
#undef GC_HPUX_THREADS
#undef GC_IRIX_THREADS
#undef GC_LINUX_THREADS
#undef GC_OSF1_THREADS
#undef GC_SOLARIS_PTHREADS
#undef GC_SOLARIS_THREADS
#undef GC_WIN32_THREADS
#undef JAVA_FINALIZATION
#undef KEEP_BACK_PTRS
#undef MAKE_BACK_GRAPH
#undef NO_DEBUGGING
#undef NO_EXECUTE_PERMISSION
#undef NO_SIGNALS
#undef NO_SIGSET
#undef PARALLEL_MARK
#undef SAVE_CALL_COUNT
#undef SILENT
#undef SOLARIS25_PROC_VDB_BUG_FIXED
#undef STACKBASE
#undef SUNOS53_SHARED_LIB
#undef THREAD_LOCAL_ALLOC
#undef _POSIX_C_SOURCE
#undef _REENTRANT
/*
* This should never be included directly. It is included only from gc.h.
* We separate it only to make gc.h more suitable as documentation.
*
* Some tests for old macros. These violate our namespace rules and will
* disappear shortly. Use the GC_ names.
*/
#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS)
# define GC_SOLARIS_THREADS
#endif
#if defined(_SOLARIS_PTHREADS)
# define GC_SOLARIS_PTHREADS
#endif
#if defined(IRIX_THREADS)
# define GC_IRIX_THREADS
#endif
#if defined(DGUX_THREADS)
# if !defined(GC_DGUX386_THREADS)
# define GC_DGUX386_THREADS
# endif
#endif
#if defined(AIX_THREADS)
# define GC_AIX_THREADS
#endif
#if defined(HPUX_THREADS)
# define GC_HPUX_THREADS
#endif
#if defined(OSF1_THREADS)
# define GC_OSF1_THREADS
#endif
#if defined(LINUX_THREADS)
# define GC_LINUX_THREADS
#endif
#if defined(WIN32_THREADS)
# define GC_WIN32_THREADS
#endif
#if defined(USE_LD_WRAP)
# define GC_USE_LD_WRAP
#endif
#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \
|| defined(GC_SOLARIS_PTHREADS) \
|| defined(GC_HPUX_THREADS) \
......
......@@ -152,6 +152,11 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
# define GC_OPERATOR_NEW_ARRAY
#endif
#if ! defined ( __BORLANDC__ ) /* Confuses the Borland compiler. */ \
&& ! defined ( __sgi )
# define GC_PLACEMENT_DELETE
#endif
enum GCPlacement {UseGC,
#ifndef GC_NAME_CONFLICT
GC=UseGC,
......@@ -165,7 +170,7 @@ class gc {public:
/* Must be redefined here, since the other overloadings */
/* hide the global definition. */
inline void operator delete( void* obj );
# ifndef __BORLANDC__ /* Confuses the Borland compiler. */
# ifdef GC_PLACEMENT_DELETE
inline void operator delete( void*, void* );
# endif
......@@ -174,7 +179,7 @@ class gc {public:
inline void* operator new[]( size_t size, GCPlacement gcp );
inline void* operator new[]( size_t size, void *p );
inline void operator delete[]( void* obj );
# ifndef __BORLANDC__
# ifdef GC_PLACEMENT_DELETE
inline void gc::operator delete[]( void*, void* );
# endif
#endif /* GC_OPERATOR_NEW_ARRAY */
......@@ -282,7 +287,7 @@ inline void* gc::operator new( size_t size, void *p ) {
inline void gc::operator delete( void* obj ) {
GC_FREE( obj );}
#ifndef __BORLANDC__
#ifdef GC_PLACEMENT_DELETE
inline void gc::operator delete( void*, void* ) {}
#endif
......@@ -300,7 +305,7 @@ inline void* gc::operator new[]( size_t size, void *p ) {
inline void gc::operator delete[]( void* obj ) {
gc::operator delete( obj );}
#ifndef __BORLANDC__
#ifdef GC_PLACEMENT_DELETE
inline void gc::operator delete[]( void*, void* ) {}
#endif
......
......@@ -53,7 +53,7 @@
/* respectively for the allocated objects. Mark_proc will be */
/* used to build the descriptor for objects allocated through the */
/* debugging interface. The mark_proc will be invoked on all such */
/* objects with an "environment" value of 1. The client may chose */
/* objects with an "environment" value of 1. The client may choose */
/* to use the same mark_proc for some of its generated mark descriptors.*/
/* In that case, it should use a different "environment" value to */
/* detect the presence or absence of the debug header. */
......@@ -88,6 +88,17 @@ extern void * GC_debug_gcj_fast_malloc(size_t lw,
extern void * GC_gcj_malloc_ignore_off_page(size_t lb,
void * ptr_to_struct_containing_descr);
/* The kind numbers of normal and debug gcj objects. */
/* Useful only for debug support, we hope. */
extern int GC_gcj_kind;
extern int GC_gcj_debug_kind;
# if defined(GC_LOCAL_ALLOC_H) && defined(GC_REDIRECT_TO_LOCAL)
--> gc_local_alloc.h should be included after this. Otherwise
--> we undo the redirection.
# endif
# ifdef GC_DEBUG
# define GC_GCJ_MALLOC(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS)
# define GC_GCJ_FAST_MALLOC(s,d) GC_debug_gcj_fast_malloc(s,d,GC_EXTRAS)
......
......@@ -61,6 +61,7 @@ GC_PTR GC_local_malloc_atomic(size_t bytes);
#endif
# ifdef GC_DEBUG
/* We don't really use local allocation in this case. */
# define GC_LOCAL_MALLOC(s) GC_debug_malloc(s,GC_EXTRAS)
# define GC_LOCAL_MALLOC_ATOMIC(s) GC_debug_malloc_atomic(s,GC_EXTRAS)
# ifdef GC_GCJ_SUPPORT
......
......@@ -19,10 +19,8 @@
* This interface should not be used by normal C or C++ clients.
* It will be useful to runtimes for other languages.
*
* Note that this file is not "namespace-clean", i.e. it introduces names
* not prefixed with GC_, which may collide with the client's names. It
* should be included only in those few places that directly provide
* information to the collector.
* This is an experts-only interface! There are many ways to break the
* collector in subtle ways by using this functionality.
*/
#ifndef GC_MARK_H
# define GC_MARK_H
......@@ -143,5 +141,63 @@ struct GC_ms_entry *GC_mark_and_push
GC_mark_and_push(obj, msp, lim, src) : \
msp)
extern size_t GC_debug_header_size;
/* The size of the header added to objects allocated through */
/* the GC_debug routines. */
/* Defined as a variable so that client mark procedures don't */
/* need to be recompiled for collector version changes. */
#define GC_USR_PTR_FROM_BASE(p) ((GC_PTR)((char *)(p) + GC_debug_header_size))
/* And some routines to support creation of new "kinds", e.g. with */
/* custom mark procedures, by language runtimes. */
/* The _inner versions assume the caller holds the allocation lock. */
/* Return a new free list array. */
void ** GC_new_free_list GC_PROTO((void));
void ** GC_new_free_list_inner GC_PROTO((void));
/* Return a new kind, as specified. */
int GC_new_kind GC_PROTO((void **free_list, GC_word mark_descriptor_template,
int add_size_to_descriptor, int clear_new_objects));
/* The last two parameters must be zero or one. */
int GC_new_kind_inner GC_PROTO((void **free_list,
GC_word mark_descriptor_template,
int add_size_to_descriptor,
int clear_new_objects));
/* Return a new mark procedure identifier, suitable for use as */
/* the first argument in GC_MAKE_PROC. */
int GC_new_proc GC_PROTO((GC_mark_proc));
int GC_new_proc_inner GC_PROTO((GC_mark_proc));
/* Allocate an object of a given kind. Note that in multithreaded */
/* contexts, this is usually unsafe for kinds that have the descriptor */
/* in the object itself, since there is otherwise a window in which */
/* the descriptor is not correct. Even in the single-threaded case, */
/* we need to be sure that cleared objects on a free list don't */
/* cause a GC crash if they are accidentally traced. */
/* ptr_t */char * GC_generic_malloc GC_PROTO((GC_word lb, int k));
/* FIXME - Should return void *, but that requires other changes. */
typedef void (*GC_describe_type_fn) GC_PROTO((void *p, char *out_buf));
/* A procedure which */
/* produces a human-readable */
/* description of the "type" of object */
/* p into the buffer out_buf of length */
/* GC_TYPE_DESCR_LEN. This is used by */
/* the debug support when printing */
/* objects. */
/* These functions should be as robust */
/* as possible, though we do avoid */
/* invoking them on objects on the */
/* global free list. */
# define GC_TYPE_DESCR_LEN 40
void GC_register_describe_type_fn GC_PROTO((int kind, GC_describe_type_fn knd));
/* Register a describe_type function */
/* to be used when printing objects */
/* of a particular kind. */
#endif /* GC_MARK_H */
......@@ -18,24 +18,4 @@
*/
void GC_finalize_all();
/*
* A version of GC_register_finalizer that allows the object to be
* finalized before the objects it references. This is again error
* prone, in that it makes it easy to accidentally reference finalized
* objects. Again, recommended only for JVM implementors.
*/
void GC_register_finalizer_no_order(GC_PTR obj,
GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR * ocd);
void GC_debug_register_finalizer_no_order(GC_PTR obj,
GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR * ocd);
#ifdef GC_DEBUG
# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
GC_debug_register_finalizer_no_order(p, f, d, of, od)
#else
# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
GC_register_finalizer_no_order(p, f, d, of, od)
#endif
......@@ -393,12 +393,12 @@ __STL_END_NAMESPACE
__STL_BEGIN_NAMESPACE
template <class _T>
struct _Alloc_traits<_T, gc_alloc >
template <class _Tp>
struct _Alloc_traits<_Tp, gc_alloc >
{
static const bool _S_instanceless = true;
typedef simple_alloc<_T, gc_alloc > _Alloc_type;
typedef __allocator<_T, gc_alloc > allocator_type;
typedef simple_alloc<_Tp, gc_alloc > _Alloc_type;
typedef __allocator<_Tp, gc_alloc > allocator_type;
};
inline bool operator==(const gc_alloc&,
......@@ -413,12 +413,12 @@ inline bool operator!=(const gc_alloc&,
return false;
}
template <class _T>
struct _Alloc_traits<_T, single_client_gc_alloc >
template <class _Tp>
struct _Alloc_traits<_Tp, single_client_gc_alloc >
{
static const bool _S_instanceless = true;
typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
typedef __allocator<_T, single_client_gc_alloc > allocator_type;
typedef simple_alloc<_Tp, single_client_gc_alloc > _Alloc_type;
typedef __allocator<_Tp, single_client_gc_alloc > allocator_type;
};
inline bool operator==(const single_client_gc_alloc&,
......@@ -433,12 +433,12 @@ inline bool operator!=(const single_client_gc_alloc&,
return false;
}
template <class _T>
struct _Alloc_traits<_T, traceable_alloc >
template <class _Tp>
struct _Alloc_traits<_Tp, traceable_alloc >
{
static const bool _S_instanceless = true;
typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
typedef __allocator<_T, traceable_alloc > allocator_type;
typedef simple_alloc<_Tp, traceable_alloc > _Alloc_type;
typedef __allocator<_Tp, traceable_alloc > allocator_type;
};
inline bool operator==(const traceable_alloc&,
......@@ -453,12 +453,12 @@ inline bool operator!=(const traceable_alloc&,
return false;
}
template <class _T>
struct _Alloc_traits<_T, single_client_traceable_alloc >
template <class _Tp>
struct _Alloc_traits<_Tp, single_client_traceable_alloc >
{
static const bool _S_instanceless = true;
typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
typedef __allocator<_T, single_client_traceable_alloc > allocator_type;
typedef simple_alloc<_Tp, single_client_traceable_alloc > _Alloc_type;
typedef __allocator<_Tp, single_client_traceable_alloc > allocator_type;
};
inline bool operator==(const single_client_traceable_alloc&,
......
......@@ -123,7 +123,6 @@ typedef struct {
# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word))
# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)
#endif
#define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh))
/* Round bytes to words without adding extra byte at end. */
#define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
......
......@@ -135,12 +135,7 @@ extern mse * GC_mark_stack;
/* Return a pointer to within 1st page of object. */
/* Set *new_hdr_p to corr. hdr. */
#ifdef __STDC__
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p,
word source);
# else
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
#else
ptr_t GC_find_start();
#endif
......
......@@ -550,7 +550,7 @@ extern GC_warn_proc GC_current_warn_proc;
#define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2)
#define MAXOBJBYTES ((word)CPP_MAXOBJBYTES)
#define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_HBLKSIZE/2)
#define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_MAXOBJBYTES)
#define MAXOBJSZ ((word)CPP_MAXOBJSZ)
# define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
......@@ -578,7 +578,7 @@ extern GC_warn_proc GC_current_warn_proc;
# else
# define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
# endif
# define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES - EXTRA_BYTES))
# define SMALL_OBJ(bytes) ((bytes) <= (MAXOBJBYTES - EXTRA_BYTES))
# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES)
# ifndef MIN_WORDS
/* MIN_WORDS is the size of the smallest allocated object. */
......@@ -615,6 +615,10 @@ extern GC_warn_proc GC_current_warn_proc;
# define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */
/* to more than 64K hblks >= 256MB. */
/* Each hash table occupies 8K bytes. */
/* Even for somewhat smaller heaps, */
/* say half that, collisions may be an */
/* issue because we blacklist */
/* addresses outside the heap. */
# endif
# endif
# define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
......@@ -934,11 +938,11 @@ struct _GC_arrays {
char _valid_offsets[VALID_OFFSET_SZ];
/* GC_valid_offsets[i] == TRUE ==> i */
/* is registered as a displacement. */
# define OFFSET_VALID(displ) \
(GC_all_interior_pointers || GC_valid_offsets[displ])
char _modws_valid_offsets[sizeof(word)];
/* GC_valid_offsets[i] ==> */
/* GC_modws_valid_offsets[i%sizeof(word)] */
# define OFFSET_VALID(displ) \
(GC_all_interior_pointers || GC_valid_offsets[displ])
# ifdef STUBBORN_ALLOC
page_hash_table _changed_pages;
/* Stubborn object pages that were changes since last call to */
......@@ -966,7 +970,7 @@ struct _GC_arrays {
# endif
# else
# ifdef SMALL_CONFIG
# define MAX_HEAP_SECTS 128 /* Roughly 1GB */
# define MAX_HEAP_SECTS 128 /* Roughly 256MB (128*2048*1K) */
# else
# define MAX_HEAP_SECTS 384 /* Roughly 3GB */
# endif
......@@ -1436,6 +1440,7 @@ GC_bool GC_is_tmp_root GC_PROTO((ptr_t p));
# endif
void GC_register_dynamic_libraries GC_PROTO((void));
/* Add dynamic library data sections to the root set. */
GC_bool GC_register_main_static_data GC_PROTO((void));
/* We need to register the main data segment. Returns */
/* TRUE unless this is done implicitly as part of */
......@@ -1610,7 +1615,7 @@ void GC_collect_a_little_inner GC_PROTO((int n));
/* collection work, if appropriate. */
/* A unit is an amount appropriate for */
/* HBLKSIZE bytes of allocation. */
ptr_t GC_generic_malloc GC_PROTO((word lb, int k));
/* ptr_t GC_generic_malloc GC_PROTO((word lb, int k)); */
/* Allocate an object of the given */
/* kind. By default, there are only */
/* a few kinds: composite(pointerfree), */
......@@ -1620,6 +1625,7 @@ ptr_t GC_generic_malloc GC_PROTO((word lb, int k));
/* internals to add more, e.g. to */
/* communicate object layout info */
/* to the collector. */
/* The actual decl is in gc_mark.h. */
ptr_t GC_generic_malloc_ignore_off_page GC_PROTO((size_t b, int k));
/* As above, but pointers past the */
/* first page of the resulting object */
......@@ -1717,6 +1723,10 @@ extern GC_bool GC_print_stats; /* Produce at least some logging output */
# define COND_DUMP
#endif
#ifdef KEEP_BACK_PTRS
extern long GC_backtraces;
#endif
/* Macros used for collector internal allocation. */
/* These assume the collector lock is held. */
#ifdef DBG_HDRS_ALL
......
......@@ -2,7 +2,7 @@
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
* Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
* Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
......@@ -307,6 +307,10 @@
# define I386
# define mach_type_known
# endif
# if defined(__NetBSD__) && defined(__x86_64__)
# define X86_64
# define mach_type_known
# endif
# if defined(bsdi) && (defined(i386) || defined(__i386__))
# define I386
# define BSDI
......@@ -347,6 +351,11 @@
# define MSWIN32 /* or Win32s */
# define mach_type_known
# endif
# if defined(_MSC_VER) && defined(_M_IA64)
# define IA64
# define MSWIN32 /* Really win64, but we don't treat 64-bit */
/* variants as a differnt platform. */
# endif
# endif
# if defined(__DJGPP__)
# define I386
......@@ -588,7 +597,8 @@
* USE_GENERIC_PUSH_REGS the preferred approach for marking from registers.
*/
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
&& !defined(__INTEL_COMPILER)
# define HAVE_BUILTIN_UNWIND_INIT
# endif
......@@ -599,8 +609,14 @@
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
# define HEURISTIC2
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# ifdef __ELF__
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# else
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
# define USE_GENERIC_PUSH_REGS
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
......@@ -612,6 +628,7 @@
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
# define USE_GENERIC_PUSH_REGS
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
......@@ -925,10 +942,17 @@
# ifdef I386
# define MACH_TYPE "I386"
# define ALIGNMENT 4 /* Appears to hold for all "32 bit" compilers */
# if defined(__LP64__) || defined(_WIN64)
# define CPP_WORDSZ 64
# define ALIGNMENT 8
# else
# define CPP_WORDSZ 32
# define ALIGNMENT 4
/* Appears to hold for all "32 bit" compilers */
/* except Borland. The -a4 option fixes */
/* Borland. */
/* Ivan Demakov: For Watcom the option is -zp4. */
# endif
# ifndef SMALL_CONFIG
# define ALIGN_DOUBLE /* Not strictly necessary, but may give speed */
/* improvement on Pentiums. */
......@@ -1042,7 +1066,7 @@
/* possibly because Linux threads is itself a malloc client */
/* and can't deal with the signals. */
# endif
# define HEAP_START 0x1000
# define HEAP_START (ptr_t)0x1000
/* This encourages mmap to give us low addresses, */
/* thus allowing the heap to grow to ~3GB */
# ifdef __ELF__
......@@ -1073,6 +1097,8 @@
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# ifdef USE_I686_PREFETCH
/* FIXME: Thus should use __builtin_prefetch, but we'll leave that */
/* for the next rtelease. */
# define PREFETCH(x) \
__asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x)))
/* Empirically prefetcht0 is much more effective at reducing */
......@@ -1562,6 +1588,7 @@
/* first putenv call. */
extern char ** environ;
# define STACKBOTTOM ((ptr_t)environ)
# define HPUX_STACKBOTTOM
# define DYNAMIC_LOADING
# include <unistd.h>
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
......@@ -1571,9 +1598,9 @@
/* address minus one page. */
# define BACKING_STORE_DISPLACEMENT 0x1000000
# define BACKING_STORE_ALIGNMENT 0x1000
# define BACKING_STORE_BASE \
(ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1) \
& ~(BACKING_STORE_ALIGNMENT - 1))
extern ptr_t GC_register_stackbottom;
# define BACKING_STORE_BASE GC_register_stackbottom
/* Known to be wrong for recent HP/UX versions!!! */
# endif
# ifdef LINUX
# define CPP_WORDSZ 64
......@@ -1591,8 +1618,8 @@
/* constants: */
# define BACKING_STORE_ALIGNMENT 0x100000
# define BACKING_STORE_DISPLACEMENT 0x80000000
extern char * GC_register_stackbottom;
# define BACKING_STORE_BASE ((ptr_t)GC_register_stackbottom)
extern ptr_t GC_register_stackbottom;
# define BACKING_STORE_BASE GC_register_stackbottom
# define SEARCH_FOR_DATA_START
# ifdef __GNUC__
# define DYNAMIC_LOADING
......@@ -1606,14 +1633,37 @@
extern int _end[];
# define DATAEND (_end)
# ifdef __GNUC__
# define PREFETCH(x) \
__asm__ (" lfetch [%0]": : "r"((void *)(x)))
# define PREFETCH_FOR_WRITE(x) \
__asm__ (" lfetch.excl [%0]": : "r"((void *)(x)))
# define CLEAR_DOUBLE(x) \
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
# ifndef __INTEL_COMPILER
# define PREFETCH(x) \
__asm__ (" lfetch [%0]": : "r"(x))
# define PREFETCH_FOR_WRITE(x) \
__asm__ (" lfetch.excl [%0]": : "r"(x))
# define CLEAR_DOUBLE(x) \
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
# else
# include <ia64intrin.h>
# define PREFETCH(x) \
__lfetch(__lfhint_none, (x))
# define PREFETCH_FOR_WRITE(x) \
__lfetch(__lfhint_nta, (x))
# define CLEAR_DOUBLE(x) \
__stf_spill((void *)(x), 0)
# endif // __INTEL_COMPILER
# endif
# endif
# ifdef MSWIN32
/* FIXME: This is a very partial guess. There is no port, yet. */
# define OS_TYPE "MSWIN32"
/* STACKBOTTOM and DATASTART are handled specially in */
/* os_dep.c. */
# define DATAEND /* not needed */
# if defined(_WIN64)
# define CPP_WORDSZ 64
# else
# define CPP_WORDSZ 32 /* Is this possible? */
# endif
# define ALIGNMENT 8
# endif
# endif
# ifdef M88K
......@@ -1801,13 +1851,28 @@
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# if defined(__GNUC__) && __GNUC__ >= 3
# define PREFETCH(x) __builtin_prefetch ((x), 0, 0)
# define PREFETCH_FOR_WRITE(x) __builtin_prefetch ((x), 1)
# if defined(__GNUC__) && __GNUC >= 3
# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
# endif
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# ifdef __ELF__
# define DYNAMIC_LOADING
# endif
# define HEURISTIC2
extern char etext[];
# define SEARCH_FOR_DATA_START
# endif
# endif
#if defined(LINUX) && defined(USE_MMAP)
/* The kernel may do a somewhat better job merging mappings etc. */
/* with anonymous mappings. */
# define USE_MMAP_ANON
#endif
#if defined(LINUX) && defined(REDIRECT_MALLOC)
/* Rld appears to allocate some memory with its own allocator, and */
/* some through malloc, which might be redirected. To make this */
......@@ -1862,9 +1927,13 @@
# define SUNOS5SIGS
# endif
# if defined(SVR4) || defined(LINUX) || defined(IRIX) || defined(HPUX) \
# if defined(FREEBSD) && (__FreeBSD__ >= 4)
# define SUNOS5SIGS
# endif
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
|| defined(DGUX) || defined(BSD) \
|| defined(DGUX) || defined(BSD) || defined(SUNOS4) \
|| defined(_AIX) || defined(DARWIN) || defined(OSF1)
# define UNIX_LIKE /* Basic Unix-like system calls work. */
# endif
......@@ -1980,6 +2049,10 @@
# define USE_GENERIC_PUSH_REGS
# endif
# if defined(MSWINCE)
# define NO_GETENV
# endif
# if defined(SPARC)
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
......
......@@ -30,6 +30,8 @@
extern size_t GC_min_stack_sz;
extern size_t GC_page_sz;
extern void GC_thr_init(void);
extern ptr_t GC_stack_alloc(size_t * stack_size);
extern void GC_stack_free(ptr_t stack, size_t size);
# endif /* GC_SOLARIS_THREADS */
......@@ -85,7 +85,7 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) {
unsigned hash_val = CACHE_HASH(qtid);
tse * volatile * entry_ptr = key -> cache + hash_val;
tse * entry = *entry_ptr; /* Must be loaded only once. */
if (EXPECT(entry -> qtid == qtid, 1)) {
if (EXPECT(entry -> qtid == qtid, 1)) {
GC_ASSERT(entry -> thread == pthread_self());
return entry -> value;
}
......
......@@ -431,6 +431,9 @@ ptr_t cold_gc_frame;
(void) setjmp(regs);
# else
(void) _setjmp(regs);
/* We don't want to mess with signals. According to */
/* SUSV3, setjmp() may or may not save signal mask. */
/* _setjmp won't, but is less portable. */
# endif
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
......
......@@ -36,6 +36,7 @@ register struct obj_kind * kind;
/* Allocate a large block of size lw words. */
/* The block is not cleared. */
/* Flags is 0 or IGNORE_OFF_PAGE. */
/* We hold the allocation lock. */
ptr_t GC_alloc_large(lw, k, flags)
word lw;
int k;
......@@ -62,20 +63,21 @@ unsigned flags;
if (h == 0) {
result = 0;
} else {
int total_bytes = BYTES_TO_WORDS(n_blocks * HBLKSIZE);
int total_bytes = n_blocks * HBLKSIZE;
if (n_blocks > 1) {
GC_large_allocd_bytes += n_blocks * HBLKSIZE;
GC_large_allocd_bytes += total_bytes;
if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
GC_max_large_allocd_bytes = GC_large_allocd_bytes;
}
result = (ptr_t) (h -> hb_body);
GC_words_wasted += total_bytes - lw;
GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
}
return result;
}
/* Allocate a large block of size lb bytes. Clear if appropriate. */
/* We hold the allocation lock. */
ptr_t GC_alloc_large_and_clear(lw, k, flags)
word lw;
int k;
......@@ -311,6 +313,19 @@ DCL_LOCK_STATE;
}
# ifdef REDIRECT_MALLOC
/* Avoid unnecessary nested procedure calls here, by #defining some */
/* malloc replacements. Otherwise we end up saving a */
/* meaningless return address in the object. It also speeds things up, */
/* but it is admittedly quite ugly. */
# ifdef GC_ADD_CALLER
# define RA GC_RETURN_ADDR,
# else
# define RA
# endif
# define GC_debug_malloc_replacement(lb) \
GC_debug_malloc(lb, RA "unknown", 0)
# ifdef __STDC__
GC_PTR malloc(size_t lb)
# else
......@@ -363,6 +378,8 @@ DCL_LOCK_STATE;
/* and thus the right thing will happen even without overriding it. */
/* This seems to be true on most Linux systems. */
#undef GC_debug_malloc_replacement
# endif /* REDIRECT_MALLOC */
/* Explicitly deallocate an object p. */
......
......@@ -147,6 +147,16 @@ int obj_kind;
# endif
# ifdef REDIRECT_REALLOC
/* As with malloc, avoid two levels of extra calls here. */
# ifdef GC_ADD_CALLER
# define RA GC_RETURN_ADDR,
# else
# define RA
# endif
# define GC_debug_realloc_replacement(p, lb) \
GC_debug_realloc(p, lb, RA "unknown", 0)
# ifdef __STDC__
GC_PTR realloc(GC_PTR p, size_t lb)
# else
......@@ -157,6 +167,8 @@ int obj_kind;
{
return(REDIRECT_REALLOC(p, lb));
}
# undef GC_debug_realloc_replacement
# endif /* REDIRECT_REALLOC */
......
......@@ -558,8 +558,8 @@ register hdr *hhdr, **new_hdr_p;
current = current - HBLKSIZE*(word)hhdr;
hhdr = HDR(current);
} while(IS_FORWARDING_ADDR_OR_NIL(hhdr));
/* current points to the start of the large object */
if (hhdr -> hb_flags & IGNORE_OFF_PAGE) return(0);
/* current points to near the start of the large object */
if (hhdr -> hb_flags & IGNORE_OFF_PAGE) return(orig);
if ((word *)orig - (word *)current
>= (ptrdiff_t)(hhdr->hb_sz)) {
/* Pointer past the end of the block */
......@@ -1739,7 +1739,7 @@ register hdr * hhdr;
{
register int sz = hhdr -> hb_sz;
if (sz < MAXOBJSZ) {
if (sz <= MAXOBJSZ) {
return(GC_page_was_dirty(h));
} else {
register ptr_t p = (ptr_t)h;
......
......@@ -116,6 +116,11 @@ GC_bool GC_print_back_height = 0;
GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */
#endif
#ifdef KEEP_BACK_PTRS
long GC_backtraces = 0; /* Number of random backtraces to */
/* generate for each GC. */
#endif
#ifdef FIND_LEAK
int GC_find_leak = 1;
#else
......@@ -470,7 +475,17 @@ void GC_init()
DISABLE_SIGNALS();
#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
if (!GC_is_initialized) {
BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
HMODULE hK32 = GetModuleHandle("kernel32.dll");
if (hK32)
(FARPROC) pfn = GetProcAddress(hK32,
"InitializeCriticalSectionAndSpinCount");
if (pfn)
pfn(&GC_allocate_ml, 4000);
else
InitializeCriticalSection (&GC_allocate_ml);
}
#endif /* MSWIN32 */
LOCK();
......@@ -537,7 +552,7 @@ int sig;
static GC_bool installed_looping_handler = FALSE;
void maybe_install_looping_handler()
static void maybe_install_looping_handler()
{
/* Install looping handler before the write fault handler, so we */
/* handle write faults correctly. */
......@@ -575,6 +590,15 @@ void GC_init_inner()
GC_dump_regularly = 1;
}
# endif
# ifdef KEEP_BACK_PTRS
{
char * backtraces_string = GETENV("GC_BACKTRACES");
if (0 != backtraces_string) {
GC_backtraces = atol(backtraces_string);
if (backtraces_string[0] == '\0') GC_backtraces = 1;
}
}
# endif
if (0 != GETENV("GC_FIND_LEAK")) {
GC_find_leak = 1;
# ifdef __STDC__
......@@ -650,14 +674,14 @@ void GC_init_inner()
|| defined(GC_SOLARIS_THREADS)
if (GC_stackbottom == 0) {
GC_stackbottom = GC_get_stack_base();
# if defined(LINUX) && defined(IA64)
# if (defined(LINUX) || defined(HPUX)) && defined(IA64)
GC_register_stackbottom = GC_get_register_stack_base();
# endif
} else {
# if defined(LINUX) && defined(IA64)
# if (defined(LINUX) || defined(HPUX)) && defined(IA64)
if (GC_register_stackbottom == 0) {
WARN("GC_register_stackbottom should be set with GC_stackbottom", 0);
/* The following is likely to fail, since we rely on */
/* The following may fail, since we may rely on */
/* alignment properties that may not hold with a user set */
/* GC_stackbottom. */
GC_register_stackbottom = GC_get_register_stack_base();
......@@ -754,7 +778,7 @@ void GC_init_inner()
}
# endif /* !SMALL_CONFIG */
COND_DUMP;
/* Get black list set up and/or incrmental GC started */
/* Get black list set up and/or incremental GC started */
if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
GC_is_initialized = TRUE;
# ifdef STUBBORN_ALLOC
......@@ -1031,7 +1055,6 @@ GC_CONST char * msg;
{
# if defined(MSWIN32)
(void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
DebugBreak();
# else
GC_err_printf1("%s\n", msg);
# endif
......@@ -1042,7 +1065,7 @@ GC_CONST char * msg;
/* about threads. */
for(;;) {}
}
# ifdef MSWIN32
# if defined(MSWIN32) || defined(MSWINCE)
DebugBreak();
# else
(void) abort();
......@@ -1064,6 +1087,75 @@ void GC_disable()
UNLOCK();
}
/* Helper procedures for new kind creation. */
void ** GC_new_free_list_inner()
{
void *result = GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (result == 0) ABORT("Failed to allocate freelist for new kind");
BZERO(result, (MAXOBJSZ+1)*sizeof(ptr_t));
return result;
}
void ** GC_new_free_list()
{
void *result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_free_list_inner();
UNLOCK(); ENABLE_SIGNALS();
return result;
}
int GC_new_kind_inner(fl, descr, adjust, clear)
void **fl;
GC_word descr;
int adjust;
int clear;
{
int result = GC_n_kinds++;
if (GC_n_kinds > MAXOBJKINDS) ABORT("Too many kinds");
GC_obj_kinds[result].ok_freelist = (ptr_t *)fl;
GC_obj_kinds[result].ok_reclaim_list = 0;
GC_obj_kinds[result].ok_descriptor = descr;
GC_obj_kinds[result].ok_relocate_descr = adjust;
GC_obj_kinds[result].ok_init = clear;
return result;
}
int GC_new_kind(fl, descr, adjust, clear)
void **fl;
GC_word descr;
int adjust;
int clear;
{
int result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_kind_inner(fl, descr, adjust, clear);
UNLOCK(); ENABLE_SIGNALS();
return result;
}
int GC_new_proc_inner(proc)
GC_mark_proc proc;
{
int result = GC_n_mark_procs++;
if (GC_n_mark_procs > MAX_MARK_PROCS) ABORT("Too many mark procedures");
GC_mark_procs[result] = proc;
return result;
}
int GC_new_proc(proc)
GC_mark_proc proc;
{
int result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_proc_inner(proc);
UNLOCK(); ENABLE_SIGNALS();
return result;
}
#if !defined(NO_DEBUGGING)
void GC_dump()
......
......@@ -104,7 +104,7 @@ ptr_t ofl;
p[3] = 0;
p += 4;
for (; p < lim; p += 4) {
PREFETCH_FOR_WRITE(p+64);
PREFETCH_FOR_WRITE((ptr_t)(p+64));
p[0] = (word)(p-4);
p[1] = 0;
CLEAR_DOUBLE(p+2);
......@@ -142,7 +142,7 @@ ptr_t ofl;
p[4] = (word)p;
p += 8;
for (; p < lim; p += 8) {
PREFETCH_FOR_WRITE(p+64);
PREFETCH_FOR_WRITE((ptr_t)(p+64));
p[0] = (word)(p-4);
p[4] = (word)p;
};
......@@ -171,10 +171,10 @@ ptr_t list;
/* If we were more serious about it, these should go inside */
/* the loops. But write prefetches usually don't seem to */
/* matter much. */
PREFETCH_FOR_WRITE((char *)h);
PREFETCH_FOR_WRITE((char *)h + 128);
PREFETCH_FOR_WRITE((char *)h + 256);
PREFETCH_FOR_WRITE((char *)h + 378);
PREFETCH_FOR_WRITE((ptr_t)h);
PREFETCH_FOR_WRITE((ptr_t)h + 128);
PREFETCH_FOR_WRITE((ptr_t)h + 256);
PREFETCH_FOR_WRITE((ptr_t)h + 378);
/* Handle small objects sizes more efficiently. For larger objects */
/* the difference is less significant. */
# ifndef SMALL_CONFIG
......
......@@ -47,6 +47,7 @@
/*#define DEBUG_THREADS 1*/
/*#define GC_ASSERTIONS*/
# include "gc.h"
# include "private/pthread_support.h"
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
......
......@@ -16,8 +16,10 @@
* Modified by Peter C. for Solaris Posix Threads.
*/
# if defined(GC_SOLARIS_PTHREADS)
# if defined(GC_SOLARIS_PTHREADS) || defined(GC_THREADS)
# include "private/gc_priv.h"
# endif
# if defined(GC_SOLARIS_PTHREADS)
# include <pthread.h>
# include <thread.h>
# include <signal.h>
......
......@@ -16,9 +16,12 @@
*/
/* Boehm, September 14, 1994 4:44 pm PDT */
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS) \
|| defined(GC_THREADS)
# include "private/gc_priv.h"
# endif
# include "private/gc_priv.h"
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
# include "private/solaris_threads.h"
# include <thread.h>
# include <synch.h>
......@@ -786,6 +789,7 @@ void GC_thr_init(void)
{
GC_thread t;
thread_t tid;
int ret;
if (GC_thr_initialized)
return;
......@@ -803,9 +807,11 @@ void GC_thr_init(void)
t = GC_new_thread(thr_self());
t -> stack_size = 0;
t -> flags = DETACHED | CLIENT_OWNS_STACK;
if (thr_create(0 /* stack */, 0 /* stack_size */, GC_thr_daemon,
0 /* arg */, THR_DETACHED | THR_DAEMON,
&tid /* thread_id */) != 0) {
ret = thr_create(0 /* stack */, 0 /* stack_size */, GC_thr_daemon,
0 /* arg */, THR_DETACHED | THR_DAEMON,
&tid /* thread_id */);
if (ret != 0) {
GC_err_printf1("Thr_create returned %ld\n", ret);
ABORT("Cant fork daemon");
}
thr_setprio(tid, 126);
......
......@@ -11,11 +11,11 @@
* modified is included with the above copyright notice.
*/
#if defined(GC_LINUX_THREADS)
#include "private/gc_priv.h" /* For GC_compare_and_exchange, GC_memory_barrier */
#include "private/specific.h"
#if defined(GC_LINUX_THREADS)
static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID};
/* A thread-specific data entry which will never */
/* appear valid to a reader. Used to fill in empty */
......
......@@ -208,7 +208,6 @@ sexpr y;
#ifdef GC_GCJ_SUPPORT
#include "gc_mark.h"
#include "private/dbg_mlc.h" /* For USR_PTR_FROM_BASE */
#include "gc_gcj.h"
/* The following struct emulates the vtable in gcj. */
......@@ -233,7 +232,7 @@ struct GC_ms_entry * fake_gcj_mark_proc(word * addr,
sexpr x;
if (1 == env) {
/* Object allocated with debug allocator. */
addr = (word *)USR_PTR_FROM_BASE(addr);
addr = (word *)GC_USR_PTR_FROM_BASE(addr);
}
x = (sexpr)(addr + 1); /* Skip the vtable pointer. */
mark_stack_ptr = GC_MARK_AND_PUSH(
......@@ -1256,9 +1255,11 @@ void run_one_test()
FAIL;
}
if (!TEST_FAIL_COUNT(1)) {
# if!(defined(RS6000) || defined(POWERPC) || defined(IA64))
# if!(defined(RS6000) || defined(POWERPC) || defined(IA64)) || defined(M68K)
/* ON RS6000s function pointers point to a descriptor in the */
/* data segment, so there should have been no failures. */
/* The same applies to IA64. Something similar seems to */
/* be going on with NetBSD/M68K. */
(void)GC_printf0("GC_is_visible produced wrong failure indication\n");
FAIL;
# endif
......@@ -1486,10 +1487,6 @@ void SetMinimumStack(long minSize)
# endif
n_tests = 0;
#if defined(__APPLE__) && defined(__MACH__)
GC_INIT();
#endif
# if defined(DJGPP)
/* No good way to determine stack base from library; do it */
/* manually on this platform. */
......@@ -1501,7 +1498,7 @@ void SetMinimumStack(long minSize)
/* Cheat and let stdio initialize toolbox for us. */
printf("Testing GC Macintosh port.\n");
# endif
GC_INIT(); /* Only needed if gc is dynamic library. */
GC_INIT(); /* Only needed on a few platforms. */
(void) GC_set_warn_proc(warn_proc);
# if (defined(MPROTECT_VDB) || defined(PROC_VDB)) \
&& !defined(MAKE_BACK_GRAPH)
......@@ -1794,9 +1791,7 @@ main()
(void)GC_printf0("pthread_default_stacksize_np failed.\n");
}
# endif /* GC_HPUX_THREADS */
# if defined(__APPLE__) && defined(__MACH__)
GC_INIT();
# endif
GC_INIT();
pthread_attr_init(&attr);
# if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
......
......@@ -192,7 +192,7 @@ int APIENTRY WinMain(
# endif
#endif
GC_init();
GC_INIT();
# if defined(MACOS) // MacOS
char* argv_[] = {"test_cpp", "10"}; // doesn't
......
......@@ -10,6 +10,7 @@ struct treenode {
struct treenode * mktree(int i) {
struct treenode * r = GC_MALLOC(sizeof(struct treenode));
if (0 == i) return 0;
if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode));
r -> x = mktree(i-1);
r -> y = mktree(i-1);
return r;
......
# include "gc_config_macros.h"
# include "private/gcconfig.h"
# include <stdio.h>
......
......@@ -348,8 +348,6 @@ mse * GC_array_mark_proc GC_PROTO((register word * addr,
mse * mark_stack_limit,
word env));
GC_descr GC_generic_array_descr;
/* Caller does not hold allocation lock. */
void GC_init_explicit_typing()
{
......@@ -370,47 +368,25 @@ void GC_init_explicit_typing()
}
GC_explicit_typing_initialized = TRUE;
/* Set up object kind with simple indirect descriptor. */
GC_eobjfreelist = (ptr_t *)
GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (GC_eobjfreelist == 0) ABORT("Couldn't allocate GC_eobjfreelist");
BZERO(GC_eobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
GC_explicit_kind = GC_n_kinds++;
GC_obj_kinds[GC_explicit_kind].ok_freelist = GC_eobjfreelist;
GC_obj_kinds[GC_explicit_kind].ok_reclaim_list = 0;
GC_obj_kinds[GC_explicit_kind].ok_descriptor =
(((word)WORDS_TO_BYTES(-1)) | GC_DS_PER_OBJECT);
GC_obj_kinds[GC_explicit_kind].ok_relocate_descr = TRUE;
GC_obj_kinds[GC_explicit_kind].ok_init = TRUE;
GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
GC_explicit_kind = GC_new_kind_inner(
(void **)GC_eobjfreelist,
(((word)WORDS_TO_BYTES(-1)) | GC_DS_PER_OBJECT),
TRUE, TRUE);
/* Descriptors are in the last word of the object. */
GC_typed_mark_proc_index = GC_n_mark_procs;
GC_mark_procs[GC_typed_mark_proc_index] = GC_typed_mark_proc;
GC_n_mark_procs++;
/* Moving this up breaks DEC AXP compiler. */
GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);
/* Set up object kind with array descriptor. */
GC_arobjfreelist = (ptr_t *)
GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (GC_arobjfreelist == 0) ABORT("Couldn't allocate GC_arobjfreelist");
BZERO(GC_arobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
if (GC_n_mark_procs >= MAX_MARK_PROCS)
ABORT("No slot for array mark proc");
GC_array_mark_proc_index = GC_n_mark_procs++;
if (GC_n_kinds >= MAXOBJKINDS)
ABORT("No kind available for array objects");
GC_array_kind = GC_n_kinds++;
GC_obj_kinds[GC_array_kind].ok_freelist = GC_arobjfreelist;
GC_obj_kinds[GC_array_kind].ok_reclaim_list = 0;
GC_obj_kinds[GC_array_kind].ok_descriptor =
GC_MAKE_PROC(GC_array_mark_proc_index, 0);;
GC_obj_kinds[GC_array_kind].ok_relocate_descr = FALSE;
GC_obj_kinds[GC_array_kind].ok_init = TRUE;
/* Descriptors are in the last word of the object. */
GC_mark_procs[GC_array_mark_proc_index] = GC_array_mark_proc;
GC_arobjfreelist = (ptr_t *)GC_new_free_list_inner();
GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);
GC_array_kind = GC_new_kind_inner(
(void **)GC_arobjfreelist,
GC_MAKE_PROC(GC_array_mark_proc_index, 0),
FALSE, TRUE);
for (i = 0; i < WORDSZ/2; i++) {
GC_descr d = (((word)(-1)) >> (WORDSZ - i)) << (WORDSZ - i);
d |= GC_DS_BITMAP;
GC_bm_table[i] = d;
}
GC_generic_array_descr = GC_MAKE_PROC(GC_array_mark_proc_index, 0);
UNLOCK();
ENABLE_SIGNALS();
}
......
......@@ -3,7 +3,7 @@
/* it to keep the old-style build process working. */
#define GC_TMP_VERSION_MAJOR 6
#define GC_TMP_VERSION_MINOR 3
#define GC_TMP_ALPHA_VERSION 1
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
#ifndef GC_NOT_ALPHA
# define GC_NOT_ALPHA 0xff
......@@ -14,7 +14,7 @@
GC_TMP_VERSION_MINOR != GC_VERSION_MINOR || \
defined(GC_ALPHA_VERSION) != (GC_TMP_ALPHA_VERSION != GC_NOT_ALPHA) || \
defined(GC_ALPHA_VERSION) && GC_TMP_ALPHA_VERSION != GC_ALPHA_VERSION
# error Inconsistent version info. Check version.h and configure.in.
# error Inconsistent version info. Check README, version.h, and configure.in.
# endif
#else
# define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
......
......@@ -130,7 +130,7 @@ static GC_thread GC_new_thread(void) {
ABORT("DuplicateHandle failed");
}
thread_table[i].stack_base = GC_get_stack_base();
/* Up until this point, GC_psuh_all_stacks considers this thread */
/* Up until this point, GC_push_all_stacks considers this thread */
/* invalid. */
if (thread_table[i].stack_base == NULL)
ABORT("Failed to find stack base in GC_new_thread");
......
2004-08-13 Bryce McKinlay <mckinlay@redhat.com>
* configure.in (GCINCS): Don't use "boehm-cflags". Instead, -I
boehm-gc's include dirs.
* configure: Rebuilt.
* include/boehm-gc.h: Include gc_config.h.
2004-08-13 Bryce McKinlay <mckinlay@redhat.com>
* java/net/InetAddress.java (loopbackAddress): Renamed from
localhostAddress.
(getByName): Return loopback address for null hostname, without
......
......@@ -7481,10 +7481,7 @@ echo "${ECHO_T}boehm" >&6
GCLIBS=../boehm-gc/libgcjgc_convenience.la
JC1GCSPEC='-fuse-boehm-gc'
GCTESTSPEC="-L`${PWDCMD-pwd}`/../boehm-gc/.libs -rpath `${PWDCMD-pwd}`/../boehm-gc/.libs"
# We also want to pick up some cpp flags required when including
# boehm-config.h. Yuck.
GCINCS="`cat ../boehm-gc/boehm-cflags`"
GCINCS='-I$(top_srcdir)/../boehm-gc/include -I../boehm-gc/include'
GCOBJS=boehm.lo
GCHDR=boehm-gc.h
# The POSIX thread support needs to know this.
......
......@@ -579,11 +579,8 @@ case "$GC" in
GCLIBS=../boehm-gc/libgcjgc_convenience.la
JC1GCSPEC='-fuse-boehm-gc'
GCTESTSPEC="-L`${PWDCMD-pwd}`/../boehm-gc/.libs -rpath `${PWDCMD-pwd}`/../boehm-gc/.libs"
# We also want to pick up some cpp flags required when including
# boehm-config.h. Yuck.
GCINCS="`cat ../boehm-gc/boehm-cflags`"
GCOBJS=boehm.lo
GCINCS='-I$(top_srcdir)/../boehm-gc/include -I../boehm-gc/include'
GCOBJS=boehm.lo
GCHDR=boehm-gc.h
# The POSIX thread support needs to know this.
AC_DEFINE(HAVE_BOEHM_GC, 1, [Define if Boehm GC in use.])
......
......@@ -26,6 +26,8 @@ extern "C"
#include <java/lang/Class.h>
#include <string.h>
#include <gc_config.h>
extern "C" void * GC_gcj_malloc(size_t, void *);
extern "C" void * GC_malloc_atomic(size_t);
#ifdef THREAD_LOCAL_ALLOC
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment