Commit 30c3de1f by Jeff Sturm Committed by Jeff Sturm

Import GC 6.3alpha1.

	* BCC_MAKEFILE: Merge with GC 6.3alpha1 release.
	* ChangeLog: Likewise.
	* Makefile.am: Likewise.
	* Makefile.direct: Likewise.
	* Makefile.dj: Likewise.
	* allchblk.c: Likewise.
	* alloc.c: Likewise.
	* backgraph.c: Likewise.
	* configure.host: Likewise.
	* configure.in: Likewise.
	* dbg_mlc.c: Likewise.
	* dyn_load.c: Likewise.
	* finalize.c: Likewise.
	* gc_cpp.cc: Likewise.
	* gc_dlopen.c: Likewise.
	* gcj_mlc.c: Likewise.
	* if_mach.c: Likewise.
	* mach_dep.c: Likewise.
	* malloc.c: Likewise.
	* mallocx.c: Likewise.
	* mark.c: Likewise.
	* mark_rts.c: Likewise.
	* misc.c: Likewise.
	* os_dep.c: Likewise.
	* ptr_chck.c: Likewise.
	* reclaim.c: Likewise.
	* solaris_pthreads.c: Likewise.
	* solaris_threads.c: Likewise.
	* sparc_mach_dep.S: Likewise.
	* threadlibs.c: Likewise.
	* typd_mlc.c: Likewise.
	* version.h: Likewise.
	* win32_threads.c: Likewise.
	* Mac_files/MacOS_Test_config.h: Likewise.
	* Mac_files/MacOS_config.h: Likewise.
	* cord/cordbscs.c: Likewise.
	* cord/cordprnt.c: Likewise.
	* cord/de_win.c: Likewise.
	* doc/README: Likewise.
	* doc/README.MacOSX: Likewise.
	* doc/README.changes: Likewise.
	* doc/README.environment: Likewise.
	* doc/README.ews4800: Likewise.
	* doc/README.linux: Likewise.
	* doc/README.macros: Likewise.
	* doc/README.win32: Likewise.
	* doc/debugging.html: Likewise.
	* doc/gcdescr.html: Likewise.
	* doc/tree.html: Likewise.
	* include/Makefile.in: Likewise.
	* include/gc.h: Likewise.
	* include/gc_cpp.h: Likewise.
	* include/gc_local_alloc.h: Likewise.
	* include/gc_mark.h: Likewise.
	* include/gc_pthread_redirects.h: Likewise.
	* include/gc_typed.h: Likewise.
	* include/new_gc_alloc.h: Likewise.
	* include/private/dbg_mlc.h: Likewise.
	* include/private/gc_hdrs.h: Likewise.
	* include/private/gc_locks.h: Likewise.
	* include/private/gc_pmark.h: Likewise.
	* include/private/gc_priv.h: Likewise.
	* include/private/gcconfig.h: Likewise.
	* include/private/solaris_threads.h: Likewise.
	* include/private/specific.h: Likewise.
	* tests/test.c: Likewise.
	* tests/test_cpp.cc: Likewise.

	* configure: Rebuild.
	* Makefile.in: Rebuild.

	* mips_sgi_mach_dep.s: Add.

	* alpha_mach_dep.s: Remove.
	* irix_threads.c: Remove.
	* linux_threads.c: Remove.
	* mips_sgi_mach_dep.S: Remove.
	* missing: Remove.
	* powerpc_macosx_mach_dep.s: Remove.
	* doc/Makefile.am: Remove.
	* doc/Makefile.in: Remove.

From-SVN: r69880
parent 1cb1de7e
# Makefile for Borland C++ 4.5 on NT # Makefile for Borland C++ 5.5 on NT
# For Borland 5.0, replace bc45 by bc5.
# If you have the Borland assembler, remove "-DUSE_GENERIC" # If you have the Borland assembler, remove "-DUSE_GENERIC"
# #
bc= c:\bc45 bc= c:\Borland\BCC55
bcbin= $(bc)\bin bcbin= $(bc)\bin
bclib= $(bc)\lib bclib= $(bc)\lib
bcinclude= $(bc)\include bcinclude= $(bc)\include
cc= $(bcbin)\bcc32 gcinclude1 = $(bc)\gc6.2\include
rc= $(bcbin)\brc32 gcinclude2 = $(bc)\gc6.2\cord
lib= $(bcbin)\tlib
link= $(bcbin)\tlink32 cc= $(bcbin)\bcc32
cflags= -R -v -vi -H -H=gc.csm -I$(bcinclude);cord -L$(bclib) \ rc= $(bcbin)\brc32
-w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0 lib= $(bcbin)\tlib
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= -DSILENT
defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
.c.obj: .c.obj:
$(cc) @&&| $(cc) @&&|
$(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c
| |
.cpp.obj: .cpp.obj:
$(cc) @&&| $(cc) @&&|
$(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp
| |
.rc.res: .rc.res:
...@@ -39,31 +41,31 @@ OBJS= $(XXXOBJS:XXX=) ...@@ -39,31 +41,31 @@ OBJS= $(XXXOBJS:XXX=)
all: gctest.exe cord\de.exe test_cpp.exe all: gctest.exe cord\de.exe test_cpp.exe
$(OBJS) test.obj: gc_priv.h gc_hdrs.h gc.h gcconfig.h MAKEFILE $(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h MAKEFILE
gc.lib: $(OBJS) gc.lib: $(OBJS)
-del gc.lib del gc.lib
tlib $* @&&| $(lib) $* @&&|
$(XXXOBJS:XXX=+) $(XXXOBJS:XXX=+)
| |
gctest.exe: tests\test.obj gc.lib gctest.exe: tests\test.obj gc.lib
$(cc) @&&| $(cc) @&&|
$(cflags) -W -e$* tests\test.obj gc.lib $(cflags) -W -e$* tests\test.obj gc.lib
| |
cord\de.obj cord\de_win.obj: cord\cord.h cord\private\cord_pos.h cord\de_win.h \ cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h \
cord\de_cmds.h cord\de_cmds.h
cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \ cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \
cord\de_win.res gc.lib cord\de_win.res gc.lib
$(cc) @&&| $(cc) @&&|
$(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \ $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \
cord\de.obj cord\de_win.obj gc.lib cord\de.obj cord\de_win.obj gc.lib
| |
$(rc) cord\de_win.res cord\de.exe $(rc) cord\de_win.res cord\de.exe
gc_cpp.obj: gc_cpp.h gc.h gc_cpp.obj: include\gc_cpp.h include\gc.h
gc_cpp.cpp: gc_cpp.cc gc_cpp.cpp: gc_cpp.cc
copy gc_cpp.cc gc_cpp.cpp copy gc_cpp.cc gc_cpp.cpp
...@@ -71,12 +73,16 @@ gc_cpp.cpp: gc_cpp.cc ...@@ -71,12 +73,16 @@ gc_cpp.cpp: gc_cpp.cc
test_cpp.cpp: tests\test_cpp.cc test_cpp.cpp: tests\test_cpp.cc
copy tests\test_cpp.cc test_cpp.cpp copy tests\test_cpp.cc test_cpp.cpp
test_cpp.exe: test_cpp.obj gc_cpp.h gc.h gc.lib test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
$(cc) @&&| $(cc) @&&|
$(cflags) -W -e$* test_cpp.obj gc.lib $(cflags) -W -e$* test_cpp.obj gc.lib
| |
scratch: scratch:
-del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm
clean:
del gc.lib
del *.obj
del tests\test.obj
2003-07-28 Jeff Sturm <jsturm@one-point.com>
Import GC 6.3alpha1.
* BCC_MAKEFILE: Merge with GC 6.3alpha1 release.
* ChangeLog: Likewise.
* Makefile.am: Likewise.
* Makefile.direct: Likewise.
* Makefile.dj: Likewise.
* allchblk.c: Likewise.
* alloc.c: Likewise.
* backgraph.c: Likewise.
* configure.host: Likewise.
* configure.in: Likewise.
* dbg_mlc.c: Likewise.
* dyn_load.c: Likewise.
* finalize.c: Likewise.
* gc_cpp.cc: Likewise.
* gc_dlopen.c: Likewise.
* gcj_mlc.c: Likewise.
* if_mach.c: Likewise.
* mach_dep.c: Likewise.
* malloc.c: Likewise.
* mallocx.c: Likewise.
* mark.c: Likewise.
* mark_rts.c: Likewise.
* misc.c: Likewise.
* os_dep.c: Likewise.
* ptr_chck.c: Likewise.
* reclaim.c: Likewise.
* solaris_pthreads.c: Likewise.
* solaris_threads.c: Likewise.
* sparc_mach_dep.S: Likewise.
* threadlibs.c: Likewise.
* typd_mlc.c: Likewise.
* version.h: Likewise.
* win32_threads.c: Likewise.
* Mac_files/MacOS_Test_config.h: Likewise.
* Mac_files/MacOS_config.h: Likewise.
* cord/cordbscs.c: Likewise.
* cord/cordprnt.c: Likewise.
* cord/de_win.c: Likewise.
* doc/README: Likewise.
* doc/README.MacOSX: Likewise.
* doc/README.changes: Likewise.
* doc/README.environment: Likewise.
* doc/README.ews4800: Likewise.
* doc/README.linux: Likewise.
* doc/README.macros: Likewise.
* doc/README.win32: Likewise.
* doc/debugging.html: Likewise.
* doc/gcdescr.html: Likewise.
* doc/tree.html: Likewise.
* include/Makefile.in: Likewise.
* include/gc.h: Likewise.
* include/gc_cpp.h: Likewise.
* include/gc_local_alloc.h: Likewise.
* include/gc_mark.h: Likewise.
* include/gc_pthread_redirects.h: Likewise.
* include/gc_typed.h: Likewise.
* include/new_gc_alloc.h: Likewise.
* include/private/dbg_mlc.h: Likewise.
* include/private/gc_hdrs.h: Likewise.
* include/private/gc_locks.h: Likewise.
* include/private/gc_pmark.h: Likewise.
* include/private/gc_priv.h: Likewise.
* include/private/gcconfig.h: Likewise.
* include/private/solaris_threads.h: Likewise.
* include/private/specific.h: Likewise.
* tests/test.c: Likewise.
* tests/test_cpp.cc: Likewise.
* configure: Rebuild.
* Makefile.in: Rebuild.
* mips_sgi_mach_dep.s: Add.
* alpha_mach_dep.s: Remove.
* irix_threads.c: Remove.
* linux_threads.c: Remove.
* mips_sgi_mach_dep.S: Remove.
* missing: Remove.
* powerpc_macosx_mach_dep.s: Remove.
* doc/Makefile.am: Remove.
* doc/Makefile.in: Remove.
2003-07-25 Roger Sayle <roger@eyesopen.com> 2003-07-25 Roger Sayle <roger@eyesopen.com>
* configure.host: Only use +ESdbgasm when using the HPUX native * configure.host: Only use +ESdbgasm when using the HPUX native
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
// implementations, and it sometimes has a significant performance // implementations, and it sometimes has a significant performance
// impact. However, it is dangerous for many not-quite-ANSI C // impact. However, it is dangerous for many not-quite-ANSI C
// programs that call things like printf in asynchronous signal handlers. // programs that call things like printf in asynchronous signal handlers.
// -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the // -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the
// new syntax "operator new[]" for allocating and deleting arrays. // new syntax "operator new[]" for allocating and deleting arrays.
// See gc_cpp.h for details. No effect on the C part of the collector. // See gc_cpp.h for details. No effect on the C part of the collector.
// This is defined implicitly in a few environments. // This is defined implicitly in a few environments.
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
// implementations, and it sometimes has a significant performance // implementations, and it sometimes has a significant performance
// impact. However, it is dangerous for many not-quite-ANSI C // impact. However, it is dangerous for many not-quite-ANSI C
// programs that call things like printf in asynchronous signal handlers. // programs that call things like printf in asynchronous signal handlers.
// -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the // -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the
// new syntax "operator new[]" for allocating and deleting arrays. // new syntax "operator new[]" for allocating and deleting arrays.
// See gc_cpp.h for details. No effect on the C part of the collector. // See gc_cpp.h for details. No effect on the C part of the collector.
// This is defined implicitly in a few environments. // This is defined implicitly in a few environments.
...@@ -86,4 +86,4 @@ ...@@ -86,4 +86,4 @@
// since some ports use malloc or calloc to obtain system memory. // since some ports use malloc or calloc to obtain system memory.
// (Probably works for UNIX, and win32.) // (Probably works for UNIX, and win32.)
// -DNO_DEBUG removes GC_dump and the debugging routines it calls. // -DNO_DEBUG removes GC_dump and the debugging routines it calls.
// Reduces code size slightly at the expense of debuggability. // Reduces code size slightly at the expense of debuggability.
\ No newline at end of file
...@@ -18,15 +18,23 @@ MULTICLEAN = true ...@@ -18,15 +18,23 @@ MULTICLEAN = true
noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la
if POWERPC_DARWIN
asm_libgc_sources = powerpc_darwin_mach_dep.s
else
asm_libgc_sources =
endif
GC_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \ GC_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c irix_threads.c \ dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c \
linux_threads.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.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 \ 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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c win32_threads.c backgraph.c win32_threads.c \
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
$(asm_libgc_sources)
EXTRA_GC_SOURCES = alpha_mach_dep.s \ EXTRA_GC_SOURCES = alpha_mach_dep.S \
mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
...@@ -63,7 +71,9 @@ TESTS = gctest ...@@ -63,7 +71,9 @@ TESTS = gctest
## FIXME: relies on internal code generated by automake. ## FIXME: relies on internal code generated by automake.
all_objs = @addobjs@ $(libgcjgc_la_OBJECTS) all_objs = @addobjs@ $(libgcjgc_la_OBJECTS)
$(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
include/private/gc_hdrs.h include/gc.h include/gc_gcj.h include/gc_mark.h include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
include/gc_pthread_redirects.h include/gc_config_macros.h \
include/gc_mark.h @addincludes@
## FIXME: we shouldn't have to do this, but automake forces us to. ## FIXME: we shouldn't have to do this, but automake forces us to.
.s.lo: .s.lo:
......
...@@ -152,7 +152,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIO ...@@ -152,7 +152,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIO
# currently probably works only with Linux. # currently probably works only with Linux.
CXXFLAGS= $(CFLAGS) -DOPERATOR_NEW_ARRAY CXXFLAGS= $(CFLAGS) -DGC_OPERATOR_NEW_ARRAY
AR= ar AR= ar
RANLIB= ranlib RANLIB= ranlib
...@@ -165,8 +165,8 @@ CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordt ...@@ -165,8 +165,8 @@ CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordt
CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \ SRCS= $(CSRCS) mips_sgi_mach_dep.S rs6000_mach_dep.s alpha_mach_dep.S \
sparc_mach_dep.s include/gc.h include/gc_typed.h \ sparc_mach_dep.S include/gc.h include/gc_typed.h \
include/private/gc_hdrs.h include/private/gc_priv.h \ include/private/gc_hdrs.h include/private/gc_priv.h \
include/private/gcconfig.h include/private/gc_mark.h \ include/private/gcconfig.h include/private/gc_mark.h \
include/gc_inl.h include/gc_inline.h gc.man \ include/gc_inl.h include/gc_inline.h gc.man \
...@@ -177,7 +177,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \ ...@@ -177,7 +177,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \
include/private/solaris_threads.h include/gc_backptr.h \ include/private/solaris_threads.h include/gc_backptr.h \
hpux_test_and_clear.s include/gc_gcj.h \ hpux_test_and_clear.s include/gc_gcj.h \
include/gc_local_alloc.h include/private/dbg_mlc.h \ include/gc_local_alloc.h include/private/dbg_mlc.h \
include/private/specific.h powerpc_macosx_mach_dep.s \ include/private/specific.h powerpc_darwin_mach_dep.s \
include/leak_detector.h $(CORD_SRCS) include/leak_detector.h $(CORD_SRCS)
OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \ OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
...@@ -284,16 +284,16 @@ liblinuxgc.so: $(OBJS) dyn_load.o ...@@ -284,16 +284,16 @@ liblinuxgc.so: $(OBJS) dyn_load.o
gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo
ln liblinuxgc.so libgc.so ln liblinuxgc.so libgc.so
mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s \ mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.S $(srcdir)/mips_ultrix_mach_dep.s \
$(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_macosx_mach_dep.s $(UTILS) $(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_darwin_mach_dep.s $(UTILS)
rm -f mach_dep.o rm -f mach_dep.o
./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.S
./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s ./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s
./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_macosx_mach_dep.s ./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_darwin_mach_dep.s
./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.s ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.S
./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.s ./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.S
./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
......
# Makefile.in generated automatically by automake 1.4 from Makefile.am # Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
...@@ -66,9 +66,11 @@ target_triplet = @target@ ...@@ -66,9 +66,11 @@ target_triplet = @target@
AR = @AR@ AR = @AR@
AS = @AS@ AS = @AS@
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CXX = @CXX@ CXX = @CXX@
CXXCPP = @CXXCPP@ CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CXXINCLUDES = @CXXINCLUDES@ CXXINCLUDES = @CXXINCLUDES@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
...@@ -89,7 +91,10 @@ RANLIB = @RANLIB@ ...@@ -89,7 +91,10 @@ RANLIB = @RANLIB@
STRIP = @STRIP@ STRIP = @STRIP@
THREADLIBS = @THREADLIBS@ THREADLIBS = @THREADLIBS@
VERSION = @VERSION@ VERSION = @VERSION@
addincludes = @addincludes@
addlibs = @addlibs@
addobjs = @addobjs@ addobjs = @addobjs@
addtests = @addtests@
gc_basedir = @gc_basedir@ gc_basedir = @gc_basedir@
mkinstalldirs = @mkinstalldirs@ mkinstalldirs = @mkinstalldirs@
target_all = @target_all@ target_all = @target_all@
...@@ -109,17 +114,21 @@ MULTIDO = true ...@@ -109,17 +114,21 @@ MULTIDO = true
MULTICLEAN = true MULTICLEAN = true
noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la
@POWERPC_DARWIN_TRUE@asm_libgc_sources = @POWERPC_DARWIN_TRUE@powerpc_darwin_mach_dep.s
@POWERPC_DARWIN_FALSE@asm_libgc_sources =
GC_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \ GC_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c irix_threads.c \ dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c \
linux_threads.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.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 \ 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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c win32_threads.c backgraph.c win32_threads.c \
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
$(asm_libgc_sources)
EXTRA_GC_SOURCES = alpha_mach_dep.s \ EXTRA_GC_SOURCES = alpha_mach_dep.S \
mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
...@@ -213,24 +222,53 @@ DEFS = @DEFS@ -I. -I$(srcdir) ...@@ -213,24 +222,53 @@ DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \ @POWERPC_DARWIN_FALSE@libgcjgc_la_OBJECTS = allchblk.lo alloc.lo \
dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \ @POWERPC_DARWIN_FALSE@blacklst.lo checksums.lo dbg_mlc.lo dyn_load.lo \
irix_threads.lo linux_threads.lo malloc.lo mallocx.lo mark.lo \ @POWERPC_DARWIN_FALSE@finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \
mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo \ @POWERPC_DARWIN_FALSE@aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \
ptr_chck.lo real_malloc.lo reclaim.lo solaris_pthreads.lo \ @POWERPC_DARWIN_FALSE@mark_rts.lo misc.lo new_hblk.lo obj_map.lo \
solaris_threads.lo specific.lo stubborn.lo typd_mlc.lo backgraph.lo \ @POWERPC_DARWIN_FALSE@os_dep.lo pcr_interface.lo ptr_chck.lo \
win32_threads.lo @POWERPC_DARWIN_FALSE@real_malloc.lo reclaim.lo solaris_pthreads.lo \
@POWERPC_DARWIN_FALSE@solaris_threads.lo specific.lo stubborn.lo \
@POWERPC_DARWIN_FALSE@typd_mlc.lo backgraph.lo win32_threads.lo \
@POWERPC_DARWIN_FALSE@pthread_support.lo pthread_stop_world.lo \
@POWERPC_DARWIN_FALSE@darwin_stop_world.lo
@POWERPC_DARWIN_TRUE@libgcjgc_la_OBJECTS = allchblk.lo alloc.lo \
@POWERPC_DARWIN_TRUE@blacklst.lo checksums.lo dbg_mlc.lo dyn_load.lo \
@POWERPC_DARWIN_TRUE@finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \
@POWERPC_DARWIN_TRUE@aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \
@POWERPC_DARWIN_TRUE@mark_rts.lo misc.lo new_hblk.lo obj_map.lo \
@POWERPC_DARWIN_TRUE@os_dep.lo pcr_interface.lo ptr_chck.lo \
@POWERPC_DARWIN_TRUE@real_malloc.lo reclaim.lo solaris_pthreads.lo \
@POWERPC_DARWIN_TRUE@solaris_threads.lo specific.lo stubborn.lo \
@POWERPC_DARWIN_TRUE@typd_mlc.lo backgraph.lo win32_threads.lo \
@POWERPC_DARWIN_TRUE@pthread_support.lo pthread_stop_world.lo \
@POWERPC_DARWIN_TRUE@darwin_stop_world.lo powerpc_darwin_mach_dep.lo
libgcjgc_convenience_la_LDFLAGS = libgcjgc_convenience_la_LDFLAGS =
libgcjgc_convenience_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo \ @POWERPC_DARWIN_FALSE@libgcjgc_convenience_la_OBJECTS = allchblk.lo \
checksums.lo dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ @POWERPC_DARWIN_FALSE@alloc.lo blacklst.lo checksums.lo dbg_mlc.lo \
headers.lo irix_threads.lo linux_threads.lo malloc.lo mallocx.lo \ @POWERPC_DARWIN_FALSE@dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
mark.lo mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo \ @POWERPC_DARWIN_FALSE@headers.lo aix_irix_threads.lo malloc.lo \
pcr_interface.lo ptr_chck.lo real_malloc.lo reclaim.lo \ @POWERPC_DARWIN_FALSE@mallocx.lo mark.lo mark_rts.lo misc.lo \
solaris_pthreads.lo solaris_threads.lo specific.lo stubborn.lo \ @POWERPC_DARWIN_FALSE@new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo \
typd_mlc.lo backgraph.lo win32_threads.lo @POWERPC_DARWIN_FALSE@ptr_chck.lo real_malloc.lo reclaim.lo \
@POWERPC_DARWIN_FALSE@solaris_pthreads.lo solaris_threads.lo \
@POWERPC_DARWIN_FALSE@specific.lo stubborn.lo typd_mlc.lo backgraph.lo \
@POWERPC_DARWIN_FALSE@win32_threads.lo pthread_support.lo \
@POWERPC_DARWIN_FALSE@pthread_stop_world.lo darwin_stop_world.lo
@POWERPC_DARWIN_TRUE@libgcjgc_convenience_la_OBJECTS = allchblk.lo \
@POWERPC_DARWIN_TRUE@alloc.lo blacklst.lo checksums.lo dbg_mlc.lo \
@POWERPC_DARWIN_TRUE@dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
@POWERPC_DARWIN_TRUE@headers.lo aix_irix_threads.lo malloc.lo \
@POWERPC_DARWIN_TRUE@mallocx.lo mark.lo mark_rts.lo misc.lo new_hblk.lo \
@POWERPC_DARWIN_TRUE@obj_map.lo os_dep.lo pcr_interface.lo ptr_chck.lo \
@POWERPC_DARWIN_TRUE@real_malloc.lo reclaim.lo solaris_pthreads.lo \
@POWERPC_DARWIN_TRUE@solaris_threads.lo specific.lo stubborn.lo \
@POWERPC_DARWIN_TRUE@typd_mlc.lo backgraph.lo win32_threads.lo \
@POWERPC_DARWIN_TRUE@pthread_support.lo pthread_stop_world.lo \
@POWERPC_DARWIN_TRUE@darwin_stop_world.lo powerpc_darwin_mach_dep.lo
check_PROGRAMS = gctest$(EXEEXT) check_PROGRAMS = gctest$(EXEEXT)
gctest_DEPENDENCIES = ./libgcjgc.la gctest_DEPENDENCIES = ./libgcjgc.la
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC) CCLD = $(CC)
DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \ DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \
...@@ -368,7 +406,7 @@ maintainer-clean-recursive: ...@@ -368,7 +406,7 @@ maintainer-clean-recursive:
dot_seen=no; \ dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \ rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \ test "$$subdir" != "." || dot_seen=yes; \
done; \ done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \ test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \ target=`echo $@ | sed s/-recursive//`; \
...@@ -598,7 +636,9 @@ mostlyclean distclean maintainer-clean ...@@ -598,7 +636,9 @@ mostlyclean distclean maintainer-clean
test.o: tests/test.c test.o: tests/test.c
$(COMPILE) -c $(srcdir)/tests/test.c $(COMPILE) -c $(srcdir)/tests/test.c
$(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
include/private/gc_hdrs.h include/gc.h include/gc_gcj.h include/gc_mark.h include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
include/gc_pthread_redirects.h include/gc_config_macros.h \
include/gc_mark.h @addincludes@
.s.lo: .s.lo:
$(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $< $(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
......
...@@ -47,12 +47,16 @@ GC_bool GC_use_entire_heap = 0; ...@@ -47,12 +47,16 @@ GC_bool GC_use_entire_heap = 0;
struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 }; struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 };
#ifndef USE_MUNMAP #ifndef USE_MUNMAP
word GC_free_bytes[N_HBLK_FLS+1] = { 0 }; word GC_free_bytes[N_HBLK_FLS+1] = { 0 };
/* Number of free bytes on each list. */ /* Number of free bytes on each list. */
/* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */ /* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */
/* > GC_max_large_allocd_bytes? */ /* > GC_max_large_allocd_bytes? */
GC_bool GC_enough_large_bytes_left(bytes,n) # ifdef __GNUC__
__inline__
# endif
static GC_bool GC_enough_large_bytes_left(bytes,n)
word bytes; word bytes;
int n; int n;
{ {
...@@ -583,11 +587,11 @@ int n; ...@@ -583,11 +587,11 @@ int n;
if (!GC_use_entire_heap if (!GC_use_entire_heap
&& size_avail != size_needed && size_avail != size_needed
&& USED_HEAP_SIZE >= GC_requested_heapsize && USED_HEAP_SIZE >= GC_requested_heapsize
&& !GC_incremental && GC_should_collect()) { && !TRUE_INCREMENTAL && GC_should_collect()) {
# ifdef USE_MUNMAP # ifdef USE_MUNMAP
continue; continue;
# else # else
/* If we enough large blocks left to cover any */ /* If we have enough large blocks left to cover any */
/* previous request for large blocks, we go ahead */ /* previous request for large blocks, we go ahead */
/* and split. Assuming a steady state, that should */ /* and split. Assuming a steady state, that should */
/* be safe. It means that we can use the full */ /* be safe. It means that we can use the full */
...@@ -595,6 +599,12 @@ int n; ...@@ -595,6 +599,12 @@ int n;
if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) { if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) {
continue; continue;
} }
/* If we are deallocating lots of memory from */
/* finalizers, fail and collect sooner rather */
/* than later. */
if (GC_finalizer_mem_freed > (GC_heapsize >> 4)) {
continue;
}
# endif /* !USE_MUNMAP */ # endif /* !USE_MUNMAP */
} }
/* If the next heap block is obviously better, go on. */ /* If the next heap block is obviously better, go on. */
......
...@@ -72,6 +72,13 @@ int GC_full_freq = 19; /* Every 20th collection is a full */ ...@@ -72,6 +72,13 @@ int GC_full_freq = 19; /* Every 20th collection is a full */
GC_bool GC_need_full_gc = FALSE; GC_bool GC_need_full_gc = FALSE;
/* Need full GC do to heap growth. */ /* Need full GC do to heap growth. */
#ifdef THREADS
GC_bool GC_world_stopped = FALSE;
# define IF_THREADS(x) x
#else
# define IF_THREADS(x)
#endif
word GC_used_heap_size_after_full = 0; word GC_used_heap_size_after_full = 0;
char * GC_copyright[] = char * GC_copyright[] =
...@@ -160,7 +167,7 @@ static word min_words_allocd() ...@@ -160,7 +167,7 @@ static word min_words_allocd()
+ (GC_large_free_bytes >> 2) + (GC_large_free_bytes >> 2)
/* use a bit more of large empty heap */ /* use a bit more of large empty heap */
+ total_root_size); + total_root_size);
if (GC_incremental) { if (TRUE_INCREMENTAL) {
return scan_size / (2 * GC_free_space_divisor); return scan_size / (2 * GC_free_space_divisor);
} else { } else {
return scan_size / GC_free_space_divisor; return scan_size / GC_free_space_divisor;
...@@ -182,7 +189,8 @@ word GC_adj_words_allocd() ...@@ -182,7 +189,8 @@ word GC_adj_words_allocd()
/* managed object should not alter result, assuming the client */ /* managed object should not alter result, assuming the client */
/* is playing by the rules. */ /* is playing by the rules. */
result = (signed_word)GC_words_allocd result = (signed_word)GC_words_allocd
- (signed_word)GC_mem_freed - expl_managed; - (signed_word)GC_mem_freed
+ (signed_word)GC_finalizer_mem_freed - expl_managed;
if (result > (signed_word)GC_words_allocd) { if (result > (signed_word)GC_words_allocd) {
result = GC_words_allocd; result = GC_words_allocd;
/* probably client bug or unfortunate scheduling */ /* probably client bug or unfortunate scheduling */
...@@ -250,7 +258,6 @@ void GC_maybe_gc() ...@@ -250,7 +258,6 @@ void GC_maybe_gc()
if (GC_should_collect()) { if (GC_should_collect()) {
if (!GC_incremental) { if (!GC_incremental) {
GC_notify_full_gc();
GC_gcollect_inner(); GC_gcollect_inner();
n_partial_gcs = 0; n_partial_gcs = 0;
return; return;
...@@ -302,10 +309,14 @@ void GC_maybe_gc() ...@@ -302,10 +309,14 @@ void GC_maybe_gc()
/* /*
* Stop the world garbage collection. Assumes lock held, signals disabled. * Stop the world garbage collection. Assumes lock held, signals disabled.
* If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE. * If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE.
* Return TRUE if we successfully completed the collection.
*/ */
GC_bool GC_try_to_collect_inner(stop_func) GC_bool GC_try_to_collect_inner(stop_func)
GC_stop_func stop_func; GC_stop_func stop_func;
{ {
# ifdef CONDPRINT
CLOCK_TYPE start_time, current_time;
# endif
if (GC_dont_gc) return FALSE; if (GC_dont_gc) return FALSE;
if (GC_incremental && GC_collection_in_progress()) { if (GC_incremental && GC_collection_in_progress()) {
# ifdef CONDPRINT # ifdef CONDPRINT
...@@ -320,8 +331,10 @@ GC_stop_func stop_func; ...@@ -320,8 +331,10 @@ GC_stop_func stop_func;
GC_collect_a_little_inner(1); GC_collect_a_little_inner(1);
} }
} }
if (stop_func == GC_never_stop_func) GC_notify_full_gc();
# ifdef CONDPRINT # ifdef CONDPRINT
if (GC_print_stats) { if (GC_print_stats) {
if (GC_print_stats) GET_TIME(start_time);
GC_printf2( GC_printf2(
"Initiating full world-stop collection %lu after %ld allocd bytes\n", "Initiating full world-stop collection %lu after %ld allocd bytes\n",
(unsigned long) GC_gc_no+1, (unsigned long) GC_gc_no+1,
...@@ -360,6 +373,13 @@ GC_stop_func stop_func; ...@@ -360,6 +373,13 @@ GC_stop_func stop_func;
return(FALSE); return(FALSE);
} }
GC_finish_collection(); GC_finish_collection();
# if defined(CONDPRINT)
if (GC_print_stats) {
GET_TIME(current_time);
GC_printf1("Complete collection took %lu msecs\n",
MS_TIME_DIFF(current_time,start_time));
}
# endif
return(TRUE); return(TRUE);
} }
...@@ -430,6 +450,7 @@ int GC_collect_a_little GC_PROTO(()) ...@@ -430,6 +450,7 @@ int GC_collect_a_little GC_PROTO(())
result = (int)GC_collection_in_progress(); result = (int)GC_collection_in_progress();
UNLOCK(); UNLOCK();
ENABLE_SIGNALS(); ENABLE_SIGNALS();
if (!result && GC_debugging_started) GC_print_all_smashed();
return(result); return(result);
} }
...@@ -448,16 +469,17 @@ GC_stop_func stop_func; ...@@ -448,16 +469,17 @@ GC_stop_func stop_func;
CLOCK_TYPE start_time, current_time; CLOCK_TYPE start_time, current_time;
# endif # endif
# if defined(REGISTER_LIBRARIES_EARLY)
GC_cond_register_dynamic_libraries();
# endif
STOP_WORLD();
# ifdef PRINTTIMES # ifdef PRINTTIMES
GET_TIME(start_time); GET_TIME(start_time);
# endif # endif
# if defined(CONDPRINT) && !defined(PRINTTIMES) # if defined(CONDPRINT) && !defined(PRINTTIMES)
if (GC_print_stats) GET_TIME(start_time); if (GC_print_stats) GET_TIME(start_time);
# endif # endif
# if defined(REGISTER_LIBRARIES_EARLY)
GC_cond_register_dynamic_libraries();
# endif
STOP_WORLD();
IF_THREADS(GC_world_stopped = TRUE);
# ifdef CONDPRINT # ifdef CONDPRINT
if (GC_print_stats) { if (GC_print_stats) {
GC_printf1("--> Marking for collection %lu ", GC_printf1("--> Marking for collection %lu ",
...@@ -488,6 +510,7 @@ GC_stop_func stop_func; ...@@ -488,6 +510,7 @@ GC_stop_func stop_func;
} }
# endif # endif
GC_deficit = i; /* Give the mutator a chance. */ GC_deficit = i; /* Give the mutator a chance. */
IF_THREADS(GC_world_stopped = FALSE);
START_WORLD(); START_WORLD();
return(FALSE); return(FALSE);
} }
...@@ -521,6 +544,8 @@ GC_stop_func stop_func; ...@@ -521,6 +544,8 @@ GC_stop_func stop_func;
(*GC_check_heap)(); (*GC_check_heap)();
} }
IF_THREADS(GC_world_stopped = FALSE);
START_WORLD();
# ifdef PRINTTIMES # ifdef PRINTTIMES
GET_TIME(current_time); GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n", GC_printf1("World-stopped marking took %lu msecs\n",
...@@ -534,7 +559,6 @@ GC_stop_func stop_func; ...@@ -534,7 +559,6 @@ GC_stop_func stop_func;
} }
# endif # endif
# endif # endif
START_WORLD();
return(TRUE); return(TRUE);
} }
...@@ -611,6 +635,7 @@ void GC_finish_collection() ...@@ -611,6 +635,7 @@ void GC_finish_collection()
GC_print_address_map(); GC_print_address_map();
} }
# endif # endif
COND_DUMP;
if (GC_find_leak) { if (GC_find_leak) {
/* Mark all objects on the free list. All objects should be */ /* Mark all objects on the free list. All objects should be */
/* marked when we're done. */ /* marked when we're done. */
...@@ -707,6 +732,7 @@ void GC_finish_collection() ...@@ -707,6 +732,7 @@ void GC_finish_collection()
GC_words_allocd = 0; GC_words_allocd = 0;
GC_words_wasted = 0; GC_words_wasted = 0;
GC_mem_freed = 0; GC_mem_freed = 0;
GC_finalizer_mem_freed = 0;
# ifdef USE_MUNMAP # ifdef USE_MUNMAP
GC_unmap_old(); GC_unmap_old();
...@@ -730,6 +756,7 @@ void GC_finish_collection() ...@@ -730,6 +756,7 @@ void GC_finish_collection()
int result; int result;
DCL_LOCK_STATE; DCL_LOCK_STATE;
if (GC_debugging_started) GC_print_all_smashed();
GC_INVOKE_FINALIZERS(); GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS(); DISABLE_SIGNALS();
LOCK(); LOCK();
...@@ -741,14 +768,17 @@ void GC_finish_collection() ...@@ -741,14 +768,17 @@ void GC_finish_collection()
EXIT_GC(); EXIT_GC();
UNLOCK(); UNLOCK();
ENABLE_SIGNALS(); ENABLE_SIGNALS();
if(result) GC_INVOKE_FINALIZERS(); if(result) {
if (GC_debugging_started) GC_print_all_smashed();
GC_INVOKE_FINALIZERS();
}
return(result); return(result);
} }
void GC_gcollect GC_PROTO(()) void GC_gcollect GC_PROTO(())
{ {
GC_notify_full_gc();
(void)GC_try_to_collect(GC_never_stop_func); (void)GC_try_to_collect(GC_never_stop_func);
if (GC_have_errors) GC_print_all_errors();
} }
word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ word GC_n_heap_sects = 0; /* Number of sections currently in heap. */
...@@ -950,7 +980,6 @@ GC_bool ignore_off_page; ...@@ -950,7 +980,6 @@ GC_bool ignore_off_page;
{ {
if (!GC_incremental && !GC_dont_gc && if (!GC_incremental && !GC_dont_gc &&
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) { (GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
GC_notify_full_gc();
GC_gcollect_inner(); GC_gcollect_inner();
} else { } else {
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor) word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
...@@ -975,7 +1004,6 @@ GC_bool ignore_off_page; ...@@ -975,7 +1004,6 @@ GC_bool ignore_off_page;
&& !GC_expand_hp_inner(needed_blocks)) { && !GC_expand_hp_inner(needed_blocks)) {
if (GC_fail_count++ < GC_max_retries) { if (GC_fail_count++ < GC_max_retries) {
WARN("Out of Memory! Trying to continue ...\n", 0); WARN("Out of Memory! Trying to continue ...\n", 0);
GC_notify_full_gc();
GC_gcollect_inner(); GC_gcollect_inner();
} else { } else {
# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) # if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
...@@ -1005,29 +1033,38 @@ ptr_t GC_allocobj(sz, kind) ...@@ -1005,29 +1033,38 @@ ptr_t GC_allocobj(sz, kind)
word sz; word sz;
int kind; int kind;
{ {
register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]); ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]);
GC_bool tried_minor = FALSE;
if (sz == 0) return(0); if (sz == 0) return(0);
while (*flh == 0) { while (*flh == 0) {
ENTER_GC(); ENTER_GC();
/* Do our share of marking work */ /* Do our share of marking work */
if(GC_incremental && !GC_dont_gc) GC_collect_a_little_inner(1); if(TRUE_INCREMENTAL) GC_collect_a_little_inner(1);
/* Sweep blocks for objects of this size */ /* Sweep blocks for objects of this size */
GC_continue_reclaim(sz, kind); GC_continue_reclaim(sz, kind);
EXIT_GC(); EXIT_GC();
if (*flh == 0) { if (*flh == 0) {
GC_new_hblk(sz, kind); GC_new_hblk(sz, kind);
} }
if (*flh == 0) { if (*flh == 0) {
ENTER_GC(); ENTER_GC();
if (!GC_collect_or_expand((word)1,FALSE)) { if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED
&& ! tried_minor ) {
GC_collect_a_little_inner(1);
tried_minor = TRUE;
} else {
if (!GC_collect_or_expand((word)1,FALSE)) {
EXIT_GC(); EXIT_GC();
return(0); return(0);
}
} }
EXIT_GC(); EXIT_GC();
} }
} }
/* Successful allocation; reset failure count. */
GC_fail_count = 0;
return(*flh); return(*flh);
} }
.arch ev6
.text
.align 4
.globl GC_push_regs
.ent GC_push_regs 2
GC_push_regs:
ldgp $gp, 0($27)
lda $sp, -16($sp)
stq $26, 0($sp)
.mask 0x04000000, 0
.frame $sp, 16, $26, 0
# $0 integer result
# $1-$8 temp regs - not preserved cross calls
# $9-$15 call saved regs
# $16-$21 argument regs - not preserved cross calls
# $22-$28 temp regs - not preserved cross calls
# $29 global pointer - not preserved cross calls
# $30 stack pointer
# define call_push(x) \
mov x, $16; \
jsr $26, GC_push_one; \
ldgp $gp, 0($26)
call_push($9)
call_push($10)
call_push($11)
call_push($12)
call_push($13)
call_push($14)
call_push($15)
# $f0-$f1 floating point results
# $f2-$f9 call saved regs
# $f10-$f30 temp regs - not preserved cross calls
# Use the most efficient transfer method for this hardware.
# Bit 1 detects the FIX extension, which includes ftoit.
amask 2, $0
bne $0, $use_stack
#undef call_push
#define call_push(x) \
ftoit x, $16; \
jsr $26, GC_push_one; \
ldgp $gp, 0($26)
call_push($f2)
call_push($f3)
call_push($f4)
call_push($f5)
call_push($f6)
call_push($f7)
call_push($f8)
call_push($f9)
ldq $26, 0($sp)
lda $sp, 16($sp)
ret $31, ($26), 1
.align 4
$use_stack:
#undef call_push
#define call_push(x) \
stt x, 8($sp); \
ldq $16, 8($sp); \
jsr $26, GC_push_one; \
ldgp $gp, 0($26)
call_push($f2)
call_push($f3)
call_push($f4)
call_push($f5)
call_push($f6)
call_push($f7)
call_push($f8)
call_push($f9)
ldq $26, 0($sp)
lda $sp, 16($sp)
ret $31, ($26), 1
.end GC_push_regs
...@@ -14,22 +14,28 @@ ...@@ -14,22 +14,28 @@
# host The configuration host # host The configuration host
# host_cpu The configuration host CPU # host_cpu The configuration host CPU
# target_optspace --enable-target-optspace ("yes", "no", "") # target_optspace --enable-target-optspace ("yes", "no", "")
# GCC should be "yes" if using gcc
# It sets the following shell variables: # It sets the following shell variables:
# gc_cflags Special CFLAGS to use when building # gc_cflags Special CFLAGS to use when building
gc_cflags=""
# We should set -fexceptions if we are using gcc and might be used # We should set -fexceptions if we are using gcc and might be used
# inside something like gcj. This is the zeroth approximation: # inside something like gcj. This is the zeroth approximation:
case "$host" in if test :"$GCC": = :yes: ; then
*-*-linux* ) gc_cflags="${gc_cflags} -fexceptions"
gc_cflags=-fexceptions else
;; case "$host" in
hppa*-*-hpux* ) hppa*-*-hpux* )
if test $GCC != "yes" ; then if test :$GCC: != :"yes": ; then
gc_cflags=+ESdbgasm gc_cflags="${gc_flags} +ESdbgasm"
fi fi
;; # :TODO: actaully we should check using Autoconf if
esac # the compiler supports this option.
;;
esac
fi
case "${target_optspace}:${host}" in case "${target_optspace}:${host}" in
yes:*) yes:*)
...@@ -48,7 +54,7 @@ esac ...@@ -48,7 +54,7 @@ esac
case "${host}" in case "${host}" in
mips-tx39-*|mipstx39-unknown-*) mips-tx39-*|mipstx39-unknown-*)
boehm_gc_cflags="${boehm_gc_cflags} -G 0" gc_cflags="${gc_cflags} -G 0"
;; ;;
*) *)
;; ;;
......
...@@ -73,10 +73,10 @@ case "$THREADS" in ...@@ -73,10 +73,10 @@ case "$THREADS" in
THREADS=posix THREADS=posix
THREADLIBS=-lpthread THREADLIBS=-lpthread
case "$host" in case "$host" in
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* ) x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*)
AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(GC_LINUX_THREADS)
AC_DEFINE(_REENTRANT) AC_DEFINE(_REENTRANT)
if test "${enable_parallel_mark}"; then if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK) AC_DEFINE(PARALLEL_MARK)
fi fi
AC_DEFINE(THREAD_LOCAL_ALLOC) AC_DEFINE(THREAD_LOCAL_ALLOC)
...@@ -85,6 +85,10 @@ case "$THREADS" in ...@@ -85,6 +85,10 @@ case "$THREADS" in
AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(GC_LINUX_THREADS)
AC_DEFINE(_REENTRANT) AC_DEFINE(_REENTRANT)
;; ;;
*-*-aix*)
AC_DEFINE(GC_AIX_THREADS)
AC_DEFINE(_REENTRANT)
;;
*-*-hpux*) *-*-hpux*)
AC_MSG_WARN("Only HP/UX 11 threads are supported.") AC_MSG_WARN("Only HP/UX 11 threads are supported.")
AC_DEFINE(GC_HPUX_THREADS) AC_DEFINE(GC_HPUX_THREADS)
...@@ -109,16 +113,52 @@ case "$THREADS" in ...@@ -109,16 +113,52 @@ case "$THREADS" in
AC_DEFINE(GC_IRIX_THREADS) AC_DEFINE(GC_IRIX_THREADS)
;; ;;
*-*-cygwin*) *-*-cygwin*)
THREADLIBS= AC_DEFINE(GC_WIN32_THREADS)
;;
*-*-darwin*)
AC_DEFINE(GC_DARWIN_THREADS)
AC_DEFINE(THREAD_LOCAL_ALLOC)
if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK)
fi
;;
*-*-osf*)
AC_DEFINE(GC_OSF1_THREADS)
if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK)
AC_DEFINE(THREAD_LOCAL_ALLOC)
# May want to enable it in other cases, too.
# Measurements havent yet been done.
fi
INCLUDES="$INCLUDES -pthread"
THREADLIBS="-lpthread -lrt"
;; ;;
esac esac
;; ;;
win32) win32)
AC_DEFINE(GC_WIN32_THREADS) AC_DEFINE(GC_WIN32_THREADS)
dnl Wine getenv may not return NULL for missing entry
AC_DEFINE(NO_GETENV) AC_DEFINE(NO_GETENV)
if test $enable_shared = yes; then ;;
AC_DEFINE(GC_DLL) dgux386)
THREADS=dgux386
AC_MSG_RESULT($THREADLIBS)
# Use pthread GCC switch
THREADLIBS=-pthread
if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK)
fi fi
AC_DEFINE(THREAD_LOCAL_ALLOC)
AC_DEFINE(GC_DGUX386_THREADS)
AC_DEFINE(DGUX_THREADS)
# Enable _POSIX4A_DRAFT10_SOURCE with flag -pthread
INCLUDES="-pthread $INCLUDES"
;;
aix)
THREADS=posix
THREADLIBS=-lpthread
AC_DEFINE(GC_AIX_THREADS)
AC_DEFINE(_REENTRANT)
;; ;;
decosf1 | irix | mach | os2 | solaris | dce | vxworks) decosf1 | irix | mach | os2 | solaris | dce | vxworks)
AC_MSG_ERROR(thread package $THREADS not yet supported) AC_MSG_ERROR(thread package $THREADS not yet supported)
...@@ -129,7 +169,22 @@ case "$THREADS" in ...@@ -129,7 +169,22 @@ case "$THREADS" in
esac esac
AC_SUBST(THREADLIBS) AC_SUBST(THREADLIBS)
AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl") case "$host" in
powerpc-*-darwin*)
powerpc_darwin=true
;;
esac
AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue)
# We never want libdl on darwin. It is a fake libdl that just ends up making
# dyld calls anyway
case "$host" in
*-*-darwin*) ;;
*)
AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl")
;;
esac
AC_SUBST(EXTRA_TEST_LIBS) AC_SUBST(EXTRA_TEST_LIBS)
target_all=libgcjgc.la target_all=libgcjgc.la
...@@ -147,6 +202,9 @@ TARGET_ECOS="$with_ecos" ...@@ -147,6 +202,9 @@ TARGET_ECOS="$with_ecos"
) )
addobjs= addobjs=
addlibs=
addincludes=
addtests=
CXXINCLUDES= CXXINCLUDES=
case "$TARGET_ECOS" in case "$TARGET_ECOS" in
no) no)
...@@ -157,21 +215,46 @@ case "$TARGET_ECOS" in ...@@ -157,21 +215,46 @@ case "$TARGET_ECOS" in
addobjs="$addobjs ecos.lo" addobjs="$addobjs ecos.lo"
;; ;;
esac esac
if test "${enable_cplusplus}" = yes; then
addincludes="$addincludes include/gc_cpp.h include/gc_allocator.h"
addtests="$addtests test_cpp"
fi
AM_CONDITIONAL(CPLUSPLUS, test "${enable_cplusplus}" = yes)
AC_SUBST(CXX) AC_SUBST(CXX)
AC_SUBST(INCLUDES) AC_SUBST(INCLUDES)
AC_SUBST(CXXINCLUDES) AC_SUBST(CXXINCLUDES)
# Configuration of shared libraries
#
AC_MSG_CHECKING(whether to build shared libraries)
AC_ENABLE_SHARED
case "$host" in
alpha-*-openbsd*)
enable_shared=no
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
;;
esac
# Configuration of machine-dependent code
#
AC_MSG_CHECKING(which machine-dependent code should be used)
machdep= machdep=
case "$host" in case "$host" in
alpha*-*-openbsd*) alpha*-*-openbsd*)
machdep="alpha_mach_dep.lo" machdep="alpha_mach_dep.lo"
if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled) AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled)
AM_DISABLE_SHARED
fi fi
;; ;;
alpha*-*-*) alpha*-*-linux*)
machdep="alpha_mach_dep.lo" machdep="alpha_mach_dep.lo"
;; ;;
i?86-*-solaris2.[[89]]*) i?86-*-solaris2.[[89]]*)
...@@ -185,12 +268,17 @@ case "$host" in ...@@ -185,12 +268,17 @@ case "$host" in
mips-dec-ultrix*) mips-dec-ultrix*)
machdep="mips_ultrix_mach-dep.lo" machdep="mips_ultrix_mach-dep.lo"
;; ;;
mips*-*-linux*) mips-nec-sysv*|mips-unknown-sysv*)
;; ;;
mips*-*-linux*)
;;
mips-*-*) mips-*-*)
machdep="mips_sgi_mach_dep.lo" machdep="mips_sgi_mach_dep.lo"
AC_DEFINE(NO_EXECUTE_PERMISSION) AC_DEFINE(NO_EXECUTE_PERMISSION)
;; ;;
sparc-*-netbsd*)
machdep="sparc_netbsd_mach_dep.lo"
;;
sparc-sun-solaris2.3*) sparc-sun-solaris2.3*)
machdep="sparc_mach_dep.lo" machdep="sparc_mach_dep.lo"
AC_DEFINE(SUNOS53_SHARED_LIB) AC_DEFINE(SUNOS53_SHARED_LIB)
...@@ -203,16 +291,65 @@ case "$host" in ...@@ -203,16 +291,65 @@ case "$host" in
;; ;;
esac esac
if test x"$machdep" = x; then if test x"$machdep" = x; then
AC_MSG_RESULT($machdep)
machdep="mach_dep.lo" machdep="mach_dep.lo"
fi fi
addobjs="$addobjs $machdep" addobjs="$addobjs $machdep"
AC_SUBST(addobjs) AC_SUBST(addobjs)
AC_SUBST(addincludes)
AC_SUBST(addlibs)
AC_SUBST(addtests)
AC_PROG_LIBTOOL
#
# Check for AViiON Machines running DGUX
#
AC_MSG_CHECKING(if host is AViiON running DGUX)
ac_is_dgux=no
AC_CHECK_HEADER(sys/dg_sys_info.h,
[ac_is_dgux=yes;])
AC_MSG_RESULT($ac_is_dgux)
## :GOTCHA: we do not check anything but sys/dg_sys_info.h
if test $ac_is_dgux = yes; then
if test "$enable_full_debug" = "yes"; then
CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
else
CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
fi
AC_SUBST(CFLAGS)
AC_SUBST(CXXFLAGS)
fi
dnl We use these options to decide which functions to include.
AC_ARG_WITH(target-subdir,
[ --with-target-subdir=SUBDIR
configuring with a cross compiler])
AC_ARG_WITH(cross-host,
[ --with-cross-host=HOST configuring with a cross compiler])
# automake wants to see AC_EXEEXT. But we don't need it. And having
# it is actually a problem, because the compiler we're passed can't
# necessarily do a full link. So we fool automake here.
if false; then
# autoconf 2.50 runs AC_EXEEXT by default, and the macro expands
# to nothing, so nothing would remain between `then' and `fi' if it
# were not for the `:' below.
:
AC_EXEEXT
fi
dnl As of 4.13a2, the collector will not properly work on Solaris when dnl As of 4.13a2, the collector will not properly work on Solaris when
dnl built with gcc and -O. So we remove -O in the appropriate case. dnl built with gcc and -O. So we remove -O in the appropriate case.
dnl
AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary)
case "$host" in case "$host" in
sparc-sun-solaris2*) sparc-sun-solaris2*|*aix*)
if test "$GCC" = yes; then if test "$GCC" = yes; then
AC_MSG_RESULT(yes)
new_CFLAGS= new_CFLAGS=
for i in $CFLAGS; do for i in $CFLAGS; do
case "$i" in case "$i" in
...@@ -224,8 +361,11 @@ case "$host" in ...@@ -224,8 +361,11 @@ case "$host" in
esac esac
done done
CFLAGS="$new_CFLAGS" CFLAGS="$new_CFLAGS"
else
AC_MSG_RESULT(no)
fi fi
;; ;;
*) AC_MSG_RESULT(no) ;;
esac esac
dnl We need to override the top-level CFLAGS. This is how we do it. dnl We need to override the top-level CFLAGS. This is how we do it.
...@@ -267,6 +407,9 @@ AC_ARG_ENABLE(full-debug, ...@@ -267,6 +407,9 @@ AC_ARG_ENABLE(full-debug,
AC_MSG_WARN("Client must not use -fomit-frame-pointer.") AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
AC_DEFINE(SAVE_CALL_COUNT, 8) AC_DEFINE(SAVE_CALL_COUNT, 8)
;; ;;
i[3456]86-*-dgux*)
AC_DEFINE(MAKE_BACK_GRAPH)
;;
esac ] esac ]
fi) fi)
......
...@@ -219,7 +219,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) ...@@ -219,7 +219,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
result->len = result_len; result->len = result_len;
result->left = x; result->left = x;
result->right = y; result->right = y;
if (depth > MAX_DEPTH) { if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result)); return(CORD_balance((CORD)result));
} else { } else {
return((CORD) result); return((CORD) result);
...@@ -260,7 +260,11 @@ CORD CORD_cat(CORD x, CORD y) ...@@ -260,7 +260,11 @@ CORD CORD_cat(CORD x, CORD y)
result->len = result_len; result->len = result_len;
result->left = x; result->left = x;
result->right = y; result->right = y;
return((CORD) result); if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
return((CORD) result);
}
} }
} }
......
...@@ -233,7 +233,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) ...@@ -233,7 +233,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
if (width == NONE && prec == NONE) { if (width == NONE && prec == NONE) {
register char c; register char c;
c = va_arg(args, int); c = (char)va_arg(args, int);
CORD_ec_append(result, c); CORD_ec_append(result, c);
goto done; goto done;
} }
...@@ -255,12 +255,18 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) ...@@ -255,12 +255,18 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
/* Use standard sprintf to perform conversion */ /* Use standard sprintf to perform conversion */
{ {
register char * buf; register char * buf;
va_list vsprintf_args = args; va_list vsprintf_args;
/* The above does not appear to be sanctioned */
/* by the ANSI C standard. */
int max_size = 0; int max_size = 0;
int res; int res;
# ifdef __va_copy
__va_copy(vsprintf_args, args);
# else
# if defined(__GNUC__) /* and probably in other cases */
va_copy(vsprintf_args, args);
# else
vsprintf_args = args;
# endif
# endif
if (width == VARIABLE) width = va_arg(args, int); if (width == VARIABLE) width = va_arg(args, int);
if (prec == VARIABLE) prec = va_arg(args, int); if (prec == VARIABLE) prec = va_arg(args, int);
if (width != NONE) max_size = width; if (width != NONE) max_size = width;
......
...@@ -249,7 +249,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, ...@@ -249,7 +249,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
case IDM_HELPABOUT: case IDM_HELPABOUT:
if( DialogBox( hInstance, "ABOUTBOX", if( DialogBox( hInstance, "ABOUTBOX",
hwnd, lpfnAboutBox ) ); hwnd, lpfnAboutBox ) )
InvalidateRect( hwnd, NULL, TRUE ); InvalidateRect( hwnd, NULL, TRUE );
return( 0 ); return( 0 );
case IDM_HELPCONTENTS: case IDM_HELPCONTENTS:
......
...@@ -60,7 +60,7 @@ ptr_t p; ...@@ -60,7 +60,7 @@ ptr_t p;
# include <stdlib.h> # include <stdlib.h>
# if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \ # if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \
|| defined(HPUX) || defined(IRIX) || defined(OSF1) || defined(HPUX) || defined(IRIX5) || defined(OSF1)
# define RANDOM() random() # define RANDOM() random()
# else # else
# define RANDOM() (long)rand() # define RANDOM() (long)rand()
...@@ -228,6 +228,8 @@ ptr_t p; ...@@ -228,6 +228,8 @@ ptr_t p;
#endif /* KEEP_BACK_PTRS */ #endif /* KEEP_BACK_PTRS */
# define CROSSES_HBLK(p, sz) \
(((word)(p + sizeof(oh) + sz - 1) ^ (word)p) >= HBLKSIZE)
/* Store debugging info into p. Return displaced pointer. */ /* Store debugging info into p. Return displaced pointer. */
/* Assumes we don't hold allocation lock. */ /* Assumes we don't hold allocation lock. */
ptr_t GC_store_debug_info(p, sz, string, integer) ptr_t GC_store_debug_info(p, sz, string, integer)
...@@ -243,6 +245,8 @@ word integer; ...@@ -243,6 +245,8 @@ word integer;
/* But that's expensive. And this way things should only appear */ /* But that's expensive. And this way things should only appear */
/* inconsistent while we're in the handler. */ /* inconsistent while we're in the handler. */
LOCK(); LOCK();
GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
# ifdef KEEP_BACK_PTRS # ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif # endif
...@@ -275,6 +279,8 @@ word integer; ...@@ -275,6 +279,8 @@ word integer;
/* There is some argument that we should disable signals here. */ /* There is some argument that we should disable signals here. */
/* But that's expensive. And this way things should only appear */ /* But that's expensive. And this way things should only appear */
/* inconsistent while we're in the handler. */ /* inconsistent while we're in the handler. */
GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
# ifdef KEEP_BACK_PTRS # ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif # endif
...@@ -324,10 +330,11 @@ ptr_t p; ...@@ -324,10 +330,11 @@ ptr_t p;
{ {
register oh * ohdr = (oh *)GC_base(p); register oh * ohdr = (oh *)GC_base(p);
GC_ASSERT(!I_HOLD_LOCK());
GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh))); GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
GC_err_puts(ohdr -> oh_string); GC_err_puts(ohdr -> oh_string);
# ifdef SHORT_DBG_HDRS # ifdef SHORT_DBG_HDRS
GC_err_printf1(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int)); GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int));
# else # else
GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int), GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
(unsigned long)(ohdr -> oh_sz)); (unsigned long)(ohdr -> oh_sz));
...@@ -342,6 +349,7 @@ ptr_t p; ...@@ -342,6 +349,7 @@ ptr_t p;
ptr_t p; ptr_t p;
# endif # endif
{ {
GC_ASSERT(!I_HOLD_LOCK());
if (GC_HAS_DEBUG_INFO(p)) { if (GC_HAS_DEBUG_INFO(p)) {
GC_print_obj(p); GC_print_obj(p);
} else { } else {
...@@ -355,6 +363,7 @@ ptr_t p, clobbered_addr; ...@@ -355,6 +363,7 @@ ptr_t p, clobbered_addr;
{ {
register oh * ohdr = (oh *)GC_base(p); register oh * ohdr = (oh *)GC_base(p);
GC_ASSERT(!I_HOLD_LOCK());
GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr, GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
(unsigned long)p); (unsigned long)p);
if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz)) if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
...@@ -376,14 +385,18 @@ ptr_t p, clobbered_addr; ...@@ -376,14 +385,18 @@ ptr_t p, clobbered_addr;
void GC_check_heap_proc GC_PROTO((void)); void GC_check_heap_proc GC_PROTO((void));
void GC_print_all_smashed_proc GC_PROTO((void));
void GC_do_nothing() {} void GC_do_nothing() {}
void GC_start_debugging() void GC_start_debugging()
{ {
# ifndef SHORT_DBG_HDRS # ifndef SHORT_DBG_HDRS
GC_check_heap = GC_check_heap_proc; GC_check_heap = GC_check_heap_proc;
GC_print_all_smashed = GC_print_all_smashed_proc;
# else # else
GC_check_heap = GC_do_nothing; GC_check_heap = GC_do_nothing;
GC_print_all_smashed = GC_do_nothing;
# endif # endif
GC_print_heap_obj = GC_debug_print_heap_obj_proc; GC_print_heap_obj = GC_debug_print_heap_obj_proc;
GC_debugging_started = TRUE; GC_debugging_started = TRUE;
...@@ -429,6 +442,62 @@ void GC_start_debugging() ...@@ -429,6 +442,62 @@ void GC_start_debugging()
return (GC_store_debug_info(result, (word)lb, s, (word)i)); return (GC_store_debug_info(result, (word)lb, s, (word)i));
} }
# ifdef __STDC__
GC_PTR GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
# else
GC_PTR GC_debug_malloc_ignore_off_page(lb, s, i)
size_t lb;
char * s;
int i;
# ifdef GC_ADD_CALLER
--> GC_ADD_CALLER not implemented for K&R C
# endif
# endif
{
GC_PTR result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES);
if (result == 0) {
GC_err_printf1("GC_debug_malloc_ignore_off_page(%ld) returning NIL (",
(unsigned long) lb);
GC_err_puts(s);
GC_err_printf1(":%ld)\n", (unsigned long)i);
return(0);
}
if (!GC_debugging_started) {
GC_start_debugging();
}
ADD_CALL_CHAIN(result, ra);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
# ifdef __STDC__
GC_PTR GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)
# else
GC_PTR GC_debug_malloc_atomic_ignore_off_page(lb, s, i)
size_t lb;
char * s;
int i;
# ifdef GC_ADD_CALLER
--> GC_ADD_CALLER not implemented for K&R C
# endif
# endif
{
GC_PTR result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES);
if (result == 0) {
GC_err_printf1("GC_debug_malloc_atomic_ignore_off_page(%ld)"
" returning NIL (", (unsigned long) lb);
GC_err_puts(s);
GC_err_printf1(":%ld)\n", (unsigned long)i);
return(0);
}
if (!GC_debugging_started) {
GC_start_debugging();
}
ADD_CALL_CHAIN(result, ra);
return (GC_store_debug_info(result, (word)lb, s, (word)i));
}
# ifdef DBG_HDRS_ALL # ifdef DBG_HDRS_ALL
/* /*
* An allocation function for internal use. * An allocation function for internal use.
...@@ -447,7 +516,7 @@ void GC_start_debugging() ...@@ -447,7 +516,7 @@ void GC_start_debugging()
(unsigned long) lb); (unsigned long) lb);
return(0); return(0);
} }
ADD_CALL_CHAIN(result, ra); ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
} }
...@@ -461,7 +530,7 @@ void GC_start_debugging() ...@@ -461,7 +530,7 @@ void GC_start_debugging()
(unsigned long) lb); (unsigned long) lb);
return(0); return(0);
} }
ADD_CALL_CHAIN(result, ra); ADD_CALL_CHAIN(result, GC_RETURN_ADDR);
return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0));
} }
# endif # endif
...@@ -592,7 +661,7 @@ GC_PTR p; ...@@ -592,7 +661,7 @@ GC_PTR p;
int i; int i;
# endif # endif
{ {
GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES); GC_PTR result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
if (result == 0) { if (result == 0) {
GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (", GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
...@@ -618,7 +687,8 @@ GC_PTR p; ...@@ -618,7 +687,8 @@ GC_PTR p;
int i; int i;
# endif # endif
{ {
GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES); GC_PTR result =
GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
if (result == 0) { if (result == 0) {
GC_err_printf1( GC_err_printf1(
...@@ -774,6 +844,45 @@ void GC_debug_free_inner(GC_PTR p) ...@@ -774,6 +844,45 @@ void GC_debug_free_inner(GC_PTR p)
} }
#ifndef SHORT_DBG_HDRS #ifndef SHORT_DBG_HDRS
/* List of smashed objects. We defer printing these, since we can't */
/* always print them nicely with the allocation lock held. */
/* We put them here instead of in GC_arrays, since it may be useful to */
/* be able to look at them with the debugger. */
#define MAX_SMASHED 20
ptr_t GC_smashed[MAX_SMASHED];
unsigned GC_n_smashed = 0;
# if defined(__STDC__) || defined(__cplusplus)
void GC_add_smashed(ptr_t smashed)
# else
void GC_add_smashed(smashed)
ptr_t smashed;
#endif
{
GC_ASSERT(GC_is_marked(GC_base(smashed)));
GC_smashed[GC_n_smashed] = smashed;
if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed;
/* In case of overflow, we keep the first MAX_SMASHED-1 */
/* entries plus the last one. */
GC_have_errors = TRUE;
}
/* Print all objects on the list. Clear the list. */
void GC_print_all_smashed_proc ()
{
unsigned i;
GC_ASSERT(!I_HOLD_LOCK());
if (GC_n_smashed == 0) return;
GC_err_printf0("GC_check_heap_block: found smashed heap objects:\n");
for (i = 0; i < GC_n_smashed; ++i) {
GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]);
GC_smashed[i] = 0;
}
GC_n_smashed = 0;
}
/* Check all marked objects in the given block for validity */ /* Check all marked objects in the given block for validity */
/*ARGSUSED*/ /*ARGSUSED*/
# if defined(__STDC__) || defined(__cplusplus) # if defined(__STDC__) || defined(__cplusplus)
...@@ -802,11 +911,7 @@ void GC_debug_free_inner(GC_PTR p) ...@@ -802,11 +911,7 @@ void GC_debug_free_inner(GC_PTR p)
&& GC_HAS_DEBUG_INFO((ptr_t)p)) { && GC_HAS_DEBUG_INFO((ptr_t)p)) {
ptr_t clobbered = GC_check_annotated_obj((oh *)p); ptr_t clobbered = GC_check_annotated_obj((oh *)p);
if (clobbered != 0) { if (clobbered != 0) GC_add_smashed(clobbered);
GC_err_printf0(
"GC_check_heap_block: found smashed location at ");
GC_print_smashed_obj((ptr_t)p, clobbered);
}
} }
word_no += sz; word_no += sz;
p += sz; p += sz;
...@@ -819,9 +924,11 @@ void GC_debug_free_inner(GC_PTR p) ...@@ -819,9 +924,11 @@ void GC_debug_free_inner(GC_PTR p)
void GC_check_heap_proc() void GC_check_heap_proc()
{ {
# ifndef SMALL_CONFIG # ifndef SMALL_CONFIG
if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) { # ifdef ALIGN_DOUBLE
ABORT("Alignment problem: object header has inappropriate size\n"); GC_STATIC_ASSERT((sizeof(oh) & (2 * sizeof(word) - 1)) == 0);
} # else
GC_STATIC_ASSERT((sizeof(oh) & (sizeof(word) - 1)) == 0);
# endif
# endif # endif
GC_apply_to_all_blocks(GC_check_heap_block, (word)0); GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
} }
...@@ -842,12 +949,12 @@ struct closure { ...@@ -842,12 +949,12 @@ struct closure {
# endif # endif
{ {
struct closure * result = struct closure * result =
# ifdef DBG_HDRS_ALL # ifdef DBG_HDRS_ALL
(struct closure *) GC_debug_malloc(sizeof (struct closure), (struct closure *) GC_debug_malloc(sizeof (struct closure),
GC_EXTRAS); GC_EXTRAS);
# else # else
(struct closure *) GC_malloc(sizeof (struct closure)); (struct closure *) GC_malloc(sizeof (struct closure));
# endif # endif
result -> cl_fn = fn; result -> cl_fn = fn;
result -> cl_data = data; result -> cl_data = data;
...@@ -908,7 +1015,7 @@ GC_PTR *ocd; ...@@ -908,7 +1015,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj); ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) { if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1( GC_err_printf1(
"GC_register_finalizer called with non-base-pointer 0x%lx\n", "GC_debug_register_finalizer called with non-base-pointer 0x%lx\n",
obj); obj);
} }
if (0 == fn) { if (0 == fn) {
...@@ -940,7 +1047,7 @@ GC_PTR *ocd; ...@@ -940,7 +1047,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj); ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) { if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1( GC_err_printf1(
"GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n", "GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
obj); obj);
} }
if (0 == fn) { if (0 == fn) {
...@@ -973,7 +1080,7 @@ GC_PTR *ocd; ...@@ -973,7 +1080,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj); ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) { if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1( GC_err_printf1(
"GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n", "GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
obj); obj);
} }
if (0 == fn) { if (0 == fn) {
......
#
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
## Process this file with automake to produce Makefile.in.
# installed documentation
#
dist_pkgdata_DATA = barrett_diagram debugging.html gc.man \
gcdescr.html README README.amiga README.arm.cross \
README.autoconf README.changes README.contributors \
README.cords README.DGUX386 README.dj README.environment \
README.ews4800 README.hp README.linux README.Mac \
README.MacOSX README.macros README.OS2 README.rs6000 \
README.sgi README.solaris2 README.uts README.win32 \
tree.html leak.html gcinterface.html scale.html \
README.darwin
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
#
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CFLAGS = @CFLAGS@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
CXXINCLUDES = @CXXINCLUDES@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
ECHO = @ECHO@
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
GC_CFLAGS = @GC_CFLAGS@
GC_VERSION = @GC_VERSION@
INCLUDES = @INCLUDES@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
MAINT = @MAINT@
MY_CFLAGS = @MY_CFLAGS@
OBJDUMP = @OBJDUMP@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
THREADLIBS = @THREADLIBS@
VERSION = @VERSION@
addincludes = @addincludes@
addlibs = @addlibs@
addobjs = @addobjs@
addtests = @addtests@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
target_all = @target_all@
# installed documentation
#
dist_pkgdata_DATA = barrett_diagram debugging.html gc.man \
gcdescr.html README README.amiga README.arm.cross \
README.autoconf README.changes README.contributors \
README.cords README.DGUX386 README.dj README.environment \
README.ews4800 README.hp README.linux README.Mac \
README.MacOSX README.macros README.OS2 README.rs6000 \
README.sgi README.solaris2 README.uts README.win32 \
tree.html leak.html gcinterface.html scale.html \
README.darwin
subdir = doc
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DATA = $(dist_pkgdata_DATA)
DIST_COMMON = README $(dist_pkgdata_DATA) Makefile.am Makefile.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f"; \
$(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f; \
done
uninstall-dist_pkgdataDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(pkgdatadir)/$$f"; \
rm -f $(DESTDIR)$(pkgdatadir)/$$f; \
done
tags: TAGS
TAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(DATA)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-dist_pkgdataDATA
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
uninstall-am: uninstall-dist_pkgdataDATA uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am info info-am install install-am install-data \
install-data-am install-dist_pkgdataDATA install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool uninstall uninstall-am \
uninstall-dist_pkgdataDATA uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
The file linux_threads.c is also The file linux_threads.c is also
Copyright (c) 1998 by Fergus Henderson. All rights reserved. Copyright (c) 1998 by Fergus Henderson. All rights reserved.
...@@ -9,8 +9,9 @@ Copyright (c) 1998 by Fergus Henderson. All rights reserved. ...@@ -9,8 +9,9 @@ Copyright (c) 1998 by Fergus Henderson. All rights reserved.
The files Makefile.am, and configure.in are The files Makefile.am, and configure.in are
Copyright (c) 2001 by Red Hat Inc. All rights reserved. Copyright (c) 2001 by Red Hat Inc. All rights reserved.
The files config.guess and a few others are copyrighted by the Free Several files supporting GNU-style builds are copyrighted by the Free
Software Foundation. Software Foundation, and carry a different license from that given
below.
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
OR IMPLIED. ANY USE IS AT YOUR OWN RISK. OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
...@@ -27,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the ...@@ -27,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 collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.) at the notice in config.guess or ltmain.sh.)
This is version 6.1alpha3 of a conservative garbage collector for C and C++. This is version 6.3alpha1 of a conservative garbage collector for C and C++.
You might find a more recent version of this at You might find a more recent version of this at
...@@ -228,10 +229,12 @@ and several of those are compatible with the collector. ...@@ -228,10 +229,12 @@ and several of those are compatible with the collector.
or equivalent is supplied. Many of these have separate README.system or equivalent is supplied. Many of these have separate README.system
files. files.
Dynamic libraries are completely supported only under SunOS Dynamic libraries are completely supported only under SunOS/Solaris,
(and even that support is not functional on the last Sun 3 release), (and even that support is not functional on the last Sun 3 release),
Linux, IRIX 5&6, HP-PA, Win32 (not Win32S) and OSF/1 on DEC AXP machines. Linux, FreeBSD, NetBSD, IRIX 5&6, HP/UX, Win32 (not Win32S) and OSF/1
On other machines we recommend that you do one of the following: on DEC AXP machines plus perhaps a few others listed near the top
of dyn_load.c. On other machines we recommend that you do one of
the following:
1) Add dynamic library support (and send us the code). 1) Add dynamic library support (and send us the code).
2) Use static versions of the libraries. 2) Use static versions of the libraries.
...@@ -245,6 +248,8 @@ On other machines we recommend that you do one of the following: ...@@ -245,6 +248,8 @@ On other machines we recommend that you do one of the following:
In all cases we assume that pointer alignment is consistent with that In all cases we assume that pointer alignment is consistent with that
enforced by the standard C compilers. If you use a nonstandard compiler enforced by the standard C compilers. If you use a nonstandard compiler
you may have to adjust the alignment parameters defined in gc_priv.h. you may have to adjust the alignment parameters defined in gc_priv.h.
Note that this may also be an issue with packed records/structs, if those
enforce less alignment for pointers.
A port to a machine that is not byte addressed, or does not use 32 bit A port to a machine that is not byte addressed, or does not use 32 bit
or 64 bit addresses will require a major effort. A port to plain MSDOS or 64 bit addresses will require a major effort. A port to plain MSDOS
......
While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested See README.darwin for the latest Darwin/MacOSX information.
it on MacOS X Server.
I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is
no longer necessary. Incremental collection is supported via mprotect/signal.
The current solution isn't really optimal because the signal handler must decode
the faulting PPC machine instruction in order to find the correct heap address.
Further, it must poke around in the register state which the kernel saved away
in some obscure register state structure before it calls the signal handler -
needless to say the layout of this structure is no where documented.
Threads and dynamic libraries are not yet supported (adding dynamic library
support via the low-level dyld API shouldn't be that hard).
The original MacOS X port was brought to you by Andrew Stone.
June, 1 2000
Dietmar Planitzer
dave.pl@ping.at
Note from Andrew Begel:
One more fix to enable gc.a to link successfully into a shared library for
MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX
disallows common symbols in anything that eventually finds its way into a
shared library. (I don't completely understand why, but -fno-common seems to
work and doesn't mess up the garbage collector's functionality).
...@@ -5,6 +5,8 @@ platforms. ...@@ -5,6 +5,8 @@ platforms.
GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed up GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed up
process start-up. process start-up.
GC_MAXIMUM_HEAP_SIZE=<bytes> - Maximum collected heap size.
GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop. GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop.
This may make it easier to debug, such a process, especially This may make it easier to debug, such a process, especially
for multithreaded platforms that don't produce usable core for multithreaded platforms that don't produce usable core
...@@ -19,6 +21,11 @@ GC_PRINT_STATS - Turn on as much logging as is easily feasible without ...@@ -19,6 +21,11 @@ GC_PRINT_STATS - Turn on as much logging as is easily feasible without
by setting GC_quiet. On by default if the collector by setting GC_quiet. On by default if the collector
was built without -DSILENT. was built without -DSILENT.
GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup
and during every collection. Very verbose. Useful
if you have a bug to report, but please include only the
last complete dump.
GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address 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 maps for the process, to stderr on every GC. Useful for
mapping root addresses to source for deciphering leak mapping root addresses to source for deciphering leak
...@@ -27,7 +34,14 @@ GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address ...@@ -27,7 +34,14 @@ GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address
GC_NPROCS=<n> - Linux w/threads only. Explicitly sets the number of processors GC_NPROCS=<n> - Linux w/threads only. Explicitly sets the number of processors
that the GC should expect to use. Note that setting this to 1 that the GC should expect to use. Note that setting this to 1
when multiple processors are available will preserve when multiple processors are available will preserve
correctness, but may lead to really horrible performance. correctness, but may lead to really horrible performance,
since the lock implementation will immediately yield without
first spinning.
GC_MARKERS=<n> - Linux w/threads and parallel marker only. Set the number
of marker threads. This is normaly set to the number of
processors. It is safer to adjust GC_MARKERS than GC_NPROCS,
since GC_MARKERS has no impact on the lock implementation.
GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing
warnings about allocations of very large blocks. warnings about allocations of very large blocks.
...@@ -62,6 +76,20 @@ GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects ...@@ -62,6 +76,20 @@ GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects
of Conservative Garbage Collectors", POPL 2001, or of Conservative Garbage Collectors", POPL 2001, or
http://lib.hpl.hp.com/techpubs/2001/HPL-2001-251.html . http://lib.hpl.hp.com/techpubs/2001/HPL-2001-251.html .
GC_RETRY_SIGNALS, GC_NO_RETRY_SIGNALS - Try to compensate for lost
thread suspend signals in linux_threads.c. On by
default for GC_OSF1_THREADS, off otherwise. Note
that this does not work around a possible loss of
thread restart signals. This seems to be necessary for
some versions of Tru64. Since we've previously seen
similar issues on some other operating systems, it
was turned into a runtime flag to enable last-minute
work-arounds.
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:
GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that, GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that,
depending on platform and collector configuration, this depending on platform and collector configuration, this
may involve write protecting pieces of the heap to may involve write protecting pieces of the heap to
...@@ -71,22 +99,20 @@ GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that, ...@@ -71,22 +99,20 @@ GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that,
Use with caution. Use with caution.
GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs. GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs.
This only has an effect if incremental collection is enabled. This only has an effect if incremental collection is
If a collection requires appreciably more time than this, enabled. If a collection requires appreciably more time
the client will be restarted, and the collector will need than this, the client will be restarted, and the collector
to do additional work to compensate. The special value will need to do additional work to compensate. The
"999999" indicates that pause time is unlimited, and the special value "999999" indicates that pause time is
incremental collector will behave completely like a unlimited, and the incremental collector will behave
simple generational collector. If the collector is completely like a simple generational collector. If
configured for parallel marking, and run on a multiprocessor, the collector is configured for parallel marking, and
incremental collection should only be used with unlimited run on a multiprocessor, incremental collection should
pause time. only be used with unlimited pause time.
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:
GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. Forces a
collection at program termination to detect leaks that would
otherwise occur after the last GC.
GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior
pointer recognition. pointer recognition.
......
See README.alpha for Linux on DEC AXP info. See README.alpha for Linux on DEC AXP info.
This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K, IA64,
and PowerPC are also integrated. They should behave similarly, except that SPARC, MIPS, Alpha and PowerPC are also integrated. They should behave
the PowerPC port lacks incremental GC support, and it is unknown to what similarly, except that the PowerPC port lacks incremental GC support, and
extent the Linux threads code is functional. See below for M68K specific it is unknown to what extent the Linux threads code is functional.
notes. See below for M68K specific notes.
Incremental GC is supported on Intel IA32 and M68K. Incremental GC is generally supported.
Dynamic libraries are supported on an ELF system. A static executable Dynamic libraries are supported on an ELF system. A static executable
should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0". should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0".
The collector appears to work with Linux threads. We have seen The collector appears to work reliably with Linux threads, but beware
intermittent hangs in sem_wait. So far we have been unable to reproduce of older versions of glibc and gdb.
these unless the process was being debugged or traced. Thus it's
possible that the only real issue is that the debugger loses
signals on rare occasions.
The garbage collector uses SIGPWR and SIGXCPU if it is used with The garbage collector uses SIGPWR and SIGXCPU if it is used with
Linux threads. These should not be touched by the client program. Linux threads. These should not be touched by the client program.
......
...@@ -21,6 +21,13 @@ registrations are ignored, but not terribly quickly.) ...@@ -21,6 +21,13 @@ registrations are ignored, but not terribly quickly.)
pointers. And the VirtualQuery call has different semantics under pointers. And the VirtualQuery call has different semantics under
the two systems, and under different versions of win32s.) 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, The collector test program "gctest" is linked as a GUI application,
but does not open any windows. Its output appears in the file 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 "gc.log". It may be started from the file manager. The hour glass
...@@ -50,13 +57,20 @@ This appears to cause problems under Windows NT and Windows 2000 (but ...@@ -50,13 +57,20 @@ This appears to cause problems under Windows NT and Windows 2000 (but
not Windows 95/98) if the memory is later passed to CreateDIBitmap. not Windows 95/98) if the memory is later passed to CreateDIBitmap.
To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC. To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC.
This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan
Clark for tracking this down.) 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.)
For Microsoft development tools, rename NT_MAKEFILE as For Microsoft development tools, rename NT_MAKEFILE as
MAKEFILE. (Make sure that the CPU environment variable is defined MAKEFILE. (Make sure that the CPU environment variable is defined
to be i386.) In order to use the gc_cpp.h C++ interface, all to be i386.) In order to use the gc_cpp.h C++ interface, all
client code should include gc_cpp.h. client code should include gc_cpp.h.
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
distribution. It is unclear (to me, Hans Boehm) whether it is feasible to
change that.
Clients may need to define GC_NOT_DLL before including gc.h, if the 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 collector was built as a static library (as it normally is in the
absence of thread support). absence of thread support).
...@@ -64,7 +78,7 @@ absence of thread support). ...@@ -64,7 +78,7 @@ absence of thread support).
For GNU-win32, use the regular makefile, possibly after uncommenting For GNU-win32, use the regular makefile, possibly after uncommenting
the line "include Makefile.DLLs". The latter should be necessary only 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. The GNU-win32 port is
believed to work only for b18, not b19, probably dues to linker changes believed to work only for b18, not b19, probably due to linker changes
in b19. This is probably fixable with a different definition of in b19. This is probably fixable with a different definition of
DATASTART and DATAEND in gcconfig.h. DATASTART and DATAEND in gcconfig.h.
...@@ -147,7 +161,7 @@ To compile the collector and testing programs use the command: ...@@ -147,7 +161,7 @@ To compile the collector and testing programs use the command:
All programs using gc should be compiled with 4-byte alignment. All programs using gc should be compiled with 4-byte alignment.
For further explanations on this see comments about Borland. For further explanations on this see comments about Borland.
If gc compiled as dll, the macro ``GC_DLL'' should be defined before If the gc is compiled as dll, the macro ``GC_DLL'' should be defined before
including "gc.h" (for example, with -DGC_DLL compiler option). It's including "gc.h" (for example, with -DGC_DLL compiler option). It's
important, otherwise resulting programs will not run. important, otherwise resulting programs will not run.
......
...@@ -248,8 +248,12 @@ The <TT>hb_last_reclaimed</tt> field will identify the collection number ...@@ -248,8 +248,12 @@ The <TT>hb_last_reclaimed</tt> field will identify the collection number
during which its block was last swept. during which its block was last swept.
<LI> Verify that the offending object still has its correct contents at <LI> Verify that the offending object still has its correct contents at
this point. this point.
The call <TT>GC_is_marked(p)</tt> from the debugger to verify that the Then call <TT>GC_is_marked(p)</tt> from the debugger to verify that the
object has not been marked, and is about to be reclaimed. object has not been marked, and is about to be reclaimed. Note that
<TT>GC_is_marked(p)</tt> expects the real address of an object (the
address of the debug header if there is one), and thus it may
be more appropriate to call <TT>GC_is_marked(GC_base(p))</tt>
instead.
<LI> Determine a path from a root, i.e. static variable, stack, or <LI> Determine a path from a root, i.e. static variable, stack, or
register variable, register variable,
to the reclaimed object. Call <TT>GC_is_marked(q)</tt> for each object to the reclaimed object. Call <TT>GC_is_marked(q)</tt> for each object
......
...@@ -207,7 +207,8 @@ signed_word * log_size_ptr; ...@@ -207,7 +207,8 @@ signed_word * log_size_ptr;
UNLOCK(); UNLOCK();
ENABLE_SIGNALS(); ENABLE_SIGNALS();
# endif # endif
new_dl = GC_oom_fn(sizeof(struct disappearing_link)); new_dl = (struct disappearing_link *)
GC_oom_fn(sizeof(struct disappearing_link));
if (0 == new_dl) { if (0 == new_dl) {
GC_finalization_failures++; GC_finalization_failures++;
return(0); return(0);
...@@ -433,7 +434,8 @@ finalization_mark_proc * mp; ...@@ -433,7 +434,8 @@ finalization_mark_proc * mp;
UNLOCK(); UNLOCK();
ENABLE_SIGNALS(); ENABLE_SIGNALS();
# endif # endif
new_fo = GC_oom_fn(sizeof(struct finalizable_object)); new_fo = (struct finalizable_object *)
GC_oom_fn(sizeof(struct finalizable_object));
if (0 == new_fo) { if (0 == new_fo) {
GC_finalization_failures++; GC_finalization_failures++;
return; return;
...@@ -759,8 +761,9 @@ int GC_should_invoke_finalizers GC_PROTO((void)) ...@@ -759,8 +761,9 @@ int GC_should_invoke_finalizers GC_PROTO((void))
/* Should be called without allocation lock. */ /* Should be called without allocation lock. */
int GC_invoke_finalizers() int GC_invoke_finalizers()
{ {
register struct finalizable_object * curr_fo; struct finalizable_object * curr_fo;
register int count = 0; int count = 0;
word mem_freed_before;
DCL_LOCK_STATE; DCL_LOCK_STATE;
while (GC_finalize_now != 0) { while (GC_finalize_now != 0) {
...@@ -768,6 +771,9 @@ int GC_invoke_finalizers() ...@@ -768,6 +771,9 @@ int GC_invoke_finalizers()
DISABLE_SIGNALS(); DISABLE_SIGNALS();
LOCK(); LOCK();
# endif # endif
if (count == 0) {
mem_freed_before = GC_mem_freed;
}
curr_fo = GC_finalize_now; curr_fo = GC_finalize_now;
# ifdef THREADS # ifdef THREADS
if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo); if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
...@@ -789,6 +795,11 @@ int GC_invoke_finalizers() ...@@ -789,6 +795,11 @@ int GC_invoke_finalizers()
GC_free((GC_PTR)curr_fo); GC_free((GC_PTR)curr_fo);
# endif # endif
} }
if (count != 0 && mem_freed_before != GC_mem_freed) {
LOCK();
GC_finalizer_mem_freed += (GC_mem_freed - mem_freed_before);
UNLOCK();
}
return count; return count;
} }
...@@ -801,7 +812,9 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void)) ...@@ -801,7 +812,9 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void))
if (GC_finalize_now == 0) return; if (GC_finalize_now == 0) return;
if (!GC_finalize_on_demand) { if (!GC_finalize_on_demand) {
(void) GC_invoke_finalizers(); (void) GC_invoke_finalizers();
GC_ASSERT(GC_finalize_now == 0); # ifndef THREADS
GC_ASSERT(GC_finalize_now == 0);
# endif /* Otherwise GC can run concurrently and add more */
return; return;
} }
if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0 if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0
...@@ -839,3 +852,17 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void)) ...@@ -839,3 +852,17 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void))
return(result); return(result);
} }
#if !defined(NO_DEBUGGING)
void GC_print_finalization_stats()
{
struct finalizable_object *fo = GC_finalize_now;
size_t ready = 0;
GC_printf2("%lu finalization table entries; %lu disappearing links\n",
GC_fo_entries, GC_dl_entries);
for (; 0 != fo; fo = fo_next(fo)) ++ready;
GC_printf1("%lu objects are eligible for immediate finalization\n", ready);
}
#endif /* NO_DEBUGGING */
...@@ -26,15 +26,13 @@ Authors: John R. Ellis and Jesse Hull ...@@ -26,15 +26,13 @@ Authors: John R. Ellis and Jesse Hull
#include "gc_cpp.h" #include "gc_cpp.h"
#ifndef _MSC_VER
/* In the Visual C++ case, we moved this into the header. */
void* operator new( size_t size ) { void* operator new( size_t size ) {
return GC_MALLOC_UNCOLLECTABLE( size );} return GC_MALLOC_UNCOLLECTABLE( size );}
void operator delete( void* obj ) { void operator delete( void* obj ) {
GC_FREE( obj );} GC_FREE( obj );}
#ifdef OPERATOR_NEW_ARRAY #ifdef GC_OPERATOR_NEW_ARRAY
void* operator new[]( size_t size ) { void* operator new[]( size_t size ) {
return GC_MALLOC_UNCOLLECTABLE( size );} return GC_MALLOC_UNCOLLECTABLE( size );}
...@@ -42,8 +40,22 @@ void* operator new[]( size_t size ) { ...@@ -42,8 +40,22 @@ void* operator new[]( size_t size ) {
void operator delete[]( void* obj ) { void operator delete[]( void* obj ) {
GC_FREE( obj );} GC_FREE( obj );}
#endif /* OPERATOR_NEW_ARRAY */ #endif /* GC_OPERATOR_NEW_ARRAY */
#endif /* _MSC_VER */ #ifdef _MSC_VER
// This new operator is used by VC++ in case of Debug builds !
void* operator new( size_t size,
int ,//nBlockUse,
const char * szFileName,
int nLine )
{
#ifndef GC_DEBUG
return GC_malloc_uncollectable( size );
#else
return GC_debug_malloc_uncollectable(size, szFileName, nLine);
#endif
}
#endif /* _MSC_VER */
...@@ -19,12 +19,14 @@ ...@@ -19,12 +19,14 @@
/* /*
* This used to be in dyn_load.c. It was extracted into a separate file * This used to be in dyn_load.c. It was extracted into a separate file
* to avoid having to link against libdl.{a,so} if the client doesn't call * to avoid having to link against libdl.{a,so} if the client doesn't call
* dlopen. -HB * dlopen. Of course this fails if the collector is in a dynamic
* library. -HB
*/ */
#include "private/gc_priv.h" #include "private/gc_priv.h"
# if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) # if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) \
|| defined(GC_SOLARIS_THREADS)
# if defined(dlopen) && !defined(GC_USE_LD_WRAP) # if defined(dlopen) && !defined(GC_USE_LD_WRAP)
/* To support various threads pkgs, gc.h interposes on dlopen by */ /* To support various threads pkgs, gc.h interposes on dlopen by */
...@@ -44,19 +46,14 @@ ...@@ -44,19 +46,14 @@
/* calls in either a multithreaded environment, or if the library */ /* calls in either a multithreaded environment, or if the library */
/* initialization code allocates substantial amounts of GC'ed memory. */ /* initialization code allocates substantial amounts of GC'ed memory. */
/* But I don't know of a better solution. */ /* But I don't know of a better solution. */
/* This can still deadlock if the client explicitly starts a GC */ static void disable_gc_for_dlopen()
/* during the dlopen. He shouldn't do that. */
static GC_bool disable_gc_for_dlopen()
{ {
GC_bool result;
LOCK(); LOCK();
result = GC_dont_gc;
while (GC_incremental && GC_collection_in_progress()) { while (GC_incremental && GC_collection_in_progress()) {
GC_collect_a_little_inner(1000); GC_collect_a_little_inner(1000);
} }
GC_dont_gc = TRUE; ++GC_dont_gc;
UNLOCK(); UNLOCK();
return(result);
} }
/* Redefine dlopen to guarantee mutual exclusion with */ /* Redefine dlopen to guarantee mutual exclusion with */
...@@ -74,10 +71,9 @@ ...@@ -74,10 +71,9 @@
#endif #endif
{ {
void * result; void * result;
GC_bool dont_gc_save;
# ifndef USE_PROC_FOR_LIBRARIES # ifndef USE_PROC_FOR_LIBRARIES
dont_gc_save = disable_gc_for_dlopen(); disable_gc_for_dlopen();
# endif # endif
# ifdef GC_USE_LD_WRAP # ifdef GC_USE_LD_WRAP
result = (void *)__real_dlopen(path, mode); result = (void *)__real_dlopen(path, mode);
...@@ -85,7 +81,7 @@ ...@@ -85,7 +81,7 @@
result = dlopen(path, mode); result = dlopen(path, mode);
# endif # endif
# ifndef USE_PROC_FOR_LIBRARIES # ifndef USE_PROC_FOR_LIBRARIES
GC_dont_gc = dont_gc_save; GC_enable(); /* undoes disable_gc_for_dlopen */
# endif # endif
return(result); return(result);
} }
......
...@@ -157,6 +157,7 @@ DCL_LOCK_STATE; ...@@ -157,6 +157,7 @@ DCL_LOCK_STATE;
GC_words_allocd += lw; GC_words_allocd += lw;
} }
*(void **)op = ptr_to_struct_containing_descr; *(void **)op = ptr_to_struct_containing_descr;
GC_ASSERT(((void **)op)[1] == 0);
UNLOCK(); UNLOCK();
} else { } else {
LOCK(); LOCK();
......
...@@ -14,7 +14,7 @@ char ** envp; ...@@ -14,7 +14,7 @@ char ** envp;
if (strcmp(MACH_TYPE, argv[1]) != 0) return(0); if (strcmp(MACH_TYPE, argv[1]) != 0) return(0);
if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0 if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0
&& strcmp(OS_TYPE, argv[2]) != 0) return(0); && strcmp(OS_TYPE, argv[2]) != 0) return(0);
printf("^^^^Starting command^^^^\n"); fprintf(stderr, "^^^^Starting command^^^^\n");
fflush(stdout); fflush(stdout);
execvp(argv[3], argv+3); execvp(argv[3], argv+3);
perror("Couldn't execute"); perror("Couldn't execute");
......
# Makefile.in generated automatically by automake 1.4 from Makefile.am # Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
...@@ -66,9 +66,11 @@ target_triplet = @target@ ...@@ -66,9 +66,11 @@ target_triplet = @target@
AR = @AR@ AR = @AR@
AS = @AS@ AS = @AS@
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CXX = @CXX@ CXX = @CXX@
CXXCPP = @CXXCPP@ CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CXXINCLUDES = @CXXINCLUDES@ CXXINCLUDES = @CXXINCLUDES@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
...@@ -89,10 +91,15 @@ RANLIB = @RANLIB@ ...@@ -89,10 +91,15 @@ RANLIB = @RANLIB@
STRIP = @STRIP@ STRIP = @STRIP@
THREADLIBS = @THREADLIBS@ THREADLIBS = @THREADLIBS@
VERSION = @VERSION@ VERSION = @VERSION@
addincludes = @addincludes@
addlibs = @addlibs@
addobjs = @addobjs@ addobjs = @addobjs@
addtests = @addtests@
gc_basedir = @gc_basedir@ gc_basedir = @gc_basedir@
mkinstalldirs = @mkinstalldirs@ mkinstalldirs = @mkinstalldirs@
target_all = @target_all@ target_all = @target_all@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
......
...@@ -134,7 +134,9 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. ...@@ -134,7 +134,9 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
#include "gc.h" #include "gc.h"
#ifndef THINK_CPLUS #ifndef THINK_CPLUS
#define _cdecl # define GC_cdecl
#else
# define GC_cdecl _cdecl
#endif #endif
#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ #if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
...@@ -159,12 +161,22 @@ enum GCPlacement {UseGC, ...@@ -159,12 +161,22 @@ enum GCPlacement {UseGC,
class gc {public: class gc {public:
inline void* operator new( size_t size ); inline void* operator new( size_t size );
inline void* operator new( size_t size, GCPlacement gcp ); inline void* operator new( size_t size, GCPlacement gcp );
inline void* operator new( size_t size, void *p );
/* Must be redefined here, since the other overloadings */
/* hide the global definition. */
inline void operator delete( void* obj ); inline void operator delete( void* obj );
# ifndef __BORLANDC__ /* Confuses the Borland compiler. */
inline void operator delete( void*, void* );
# endif
#ifdef GC_OPERATOR_NEW_ARRAY #ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[]( size_t size ); inline void* operator new[]( size_t size );
inline void* operator new[]( size_t size, GCPlacement gcp ); inline void* operator new[]( size_t size, GCPlacement gcp );
inline void* operator new[]( size_t size, void *p );
inline void operator delete[]( void* obj ); inline void operator delete[]( void* obj );
# ifndef __BORLANDC__
inline void gc::operator delete[]( void*, void* );
# endif
#endif /* GC_OPERATOR_NEW_ARRAY */ #endif /* GC_OPERATOR_NEW_ARRAY */
}; };
/* /*
...@@ -176,7 +188,7 @@ class gc_cleanup: virtual public gc {public: ...@@ -176,7 +188,7 @@ class gc_cleanup: virtual public gc {public:
inline gc_cleanup(); inline gc_cleanup();
inline virtual ~gc_cleanup(); inline virtual ~gc_cleanup();
private: private:
inline static void _cdecl cleanup( void* obj, void* clientData );}; inline static void GC_cdecl cleanup( void* obj, void* clientData );};
/* /*
Instances of classes derived from "gc_cleanup" will be allocated Instances of classes derived from "gc_cleanup" will be allocated
in the collected heap by default. When the collector discovers an in the collected heap by default. When the collector discovers an
...@@ -211,7 +223,6 @@ inline void* operator new( ...@@ -211,7 +223,6 @@ inline void* operator new(
classes derived from "gc_cleanup" or containing members derived classes derived from "gc_cleanup" or containing members derived
from "gc_cleanup". */ from "gc_cleanup". */
#ifdef GC_OPERATOR_NEW_ARRAY
#ifdef _MSC_VER #ifdef _MSC_VER
/** This ensures that the system default operator new[] doesn't get /** This ensures that the system default operator new[] doesn't get
...@@ -220,42 +231,24 @@ inline void* operator new( ...@@ -220,42 +231,24 @@ inline void* operator new(
* There seems to be really redirect new in this environment without * There seems to be really redirect new in this environment without
* including this everywhere. * including this everywhere.
*/ */
inline void *operator new[]( size_t size ) void *operator new[]( size_t size );
{
return GC_MALLOC_UNCOLLECTABLE( size ); void operator delete[](void* obj);
}
inline void operator delete[](void* obj)
{
GC_FREE(obj);
};
inline void* operator new( size_t size)
{
return GC_MALLOC_UNCOLLECTABLE( size);
};
inline void operator delete(void* obj) void* operator new( size_t size);
{
GC_FREE(obj);
};
void operator delete(void* obj);
// This new operator is used by VC++ in case of Debug builds ! // This new operator is used by VC++ in case of Debug builds !
inline void* operator new( size_t size, void* operator new( size_t size,
int ,//nBlockUse, int ,//nBlockUse,
const char * szFileName, const char * szFileName,
int nLine int nLine );
) {
# ifndef GC_DEBUG
return GC_malloc_uncollectable( size );
# else
return GC_debug_malloc_uncollectable(size, szFileName, nLine);
# endif
}
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[]( inline void* operator new[](
size_t size, size_t size,
GCPlacement gcp, GCPlacement gcp,
...@@ -283,9 +276,15 @@ inline void* gc::operator new( size_t size, GCPlacement gcp ) { ...@@ -283,9 +276,15 @@ inline void* gc::operator new( size_t size, GCPlacement gcp ) {
else else
return GC_MALLOC_UNCOLLECTABLE( size );} return GC_MALLOC_UNCOLLECTABLE( size );}
inline void* gc::operator new( size_t size, void *p ) {
return p;}
inline void gc::operator delete( void* obj ) { inline void gc::operator delete( void* obj ) {
GC_FREE( obj );} GC_FREE( obj );}
#ifndef __BORLANDC__
inline void gc::operator delete( void*, void* ) {}
#endif
#ifdef GC_OPERATOR_NEW_ARRAY #ifdef GC_OPERATOR_NEW_ARRAY
...@@ -295,14 +294,21 @@ inline void* gc::operator new[]( size_t size ) { ...@@ -295,14 +294,21 @@ inline void* gc::operator new[]( size_t size ) {
inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { inline void* gc::operator new[]( size_t size, GCPlacement gcp ) {
return gc::operator new( size, gcp );} return gc::operator new( size, gcp );}
inline void* gc::operator new[]( size_t size, void *p ) {
return p;}
inline void gc::operator delete[]( void* obj ) { inline void gc::operator delete[]( void* obj ) {
gc::operator delete( obj );} gc::operator delete( obj );}
#ifndef __BORLANDC__
inline void gc::operator delete[]( void*, void* ) {}
#endif
#endif /* GC_OPERATOR_NEW_ARRAY */ #endif /* GC_OPERATOR_NEW_ARRAY */
inline gc_cleanup::~gc_cleanup() { inline gc_cleanup::~gc_cleanup() {
GC_REGISTER_FINALIZER_IGNORE_SELF( GC_base(this), 0, 0, 0, 0 );} GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );}
inline void gc_cleanup::cleanup( void* obj, void* displ ) { inline void gc_cleanup::cleanup( void* obj, void* displ ) {
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
* -DTHREAD_LOCAL_ALLOC, which is currently supported only on Linux. * -DTHREAD_LOCAL_ALLOC, which is currently supported only on Linux.
* *
* The debugging allocators use standard, not thread-local allocation. * The debugging allocators use standard, not thread-local allocation.
*
* These routines normally require an explicit call to GC_init(), though
* that may be done from a constructor function.
*/ */
#ifndef GC_LOCAL_ALLOC_H #ifndef GC_LOCAL_ALLOC_H
......
...@@ -129,7 +129,9 @@ extern GC_PTR GC_greatest_plausible_heap_addr; ...@@ -129,7 +129,9 @@ extern GC_PTR GC_greatest_plausible_heap_addr;
/* be reserved for exceptional cases. That will ensure that */ /* be reserved for exceptional cases. That will ensure that */
/* performance of this call is not extremely performance critical. */ /* performance of this call is not extremely performance critical. */
/* (Otherwise we would need to inline GC_mark_and_push completely, */ /* (Otherwise we would need to inline GC_mark_and_push completely, */
/* which would tie the client code to a fixed colllector version.) */ /* which would tie the client code to a fixed collector version.) */
/* Note that mark procedures should explicitly call FIXUP_POINTER() */
/* if required. */
struct GC_ms_entry *GC_mark_and_push struct GC_ms_entry *GC_mark_and_push
GC_PROTO((GC_PTR obj, GC_PROTO((GC_PTR obj,
struct GC_ms_entry * mark_stack_ptr, struct GC_ms_entry * mark_stack_ptr,
......
...@@ -52,15 +52,30 @@ ...@@ -52,15 +52,30 @@
int GC_pthread_create(pthread_t *new_thread, int GC_pthread_create(pthread_t *new_thread,
const pthread_attr_t *attr, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg); void *(*start_routine)(void *), void *arg);
#ifndef GC_DARWIN_THREADS
int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
#endif
int GC_pthread_join(pthread_t thread, void **retval); int GC_pthread_join(pthread_t thread, void **retval);
int GC_pthread_detach(pthread_t thread); int GC_pthread_detach(pthread_t thread);
#if defined(GC_OSF1_THREADS) \
&& defined(_PTHREAD_USE_MANGLED_NAMES_) && !defined(_PTHREAD_USE_PTDNAM_)
/* Unless the compiler supports #pragma extern_prefix, the Tru64 UNIX
<pthread.h> redefines some POSIX thread functions to use mangled names.
If so, undef them before redefining. */
# undef pthread_create
# undef pthread_join
# undef pthread_detach
#endif
# define pthread_create GC_pthread_create # define pthread_create GC_pthread_create
# define pthread_sigmask GC_pthread_sigmask
# define pthread_join GC_pthread_join # define pthread_join GC_pthread_join
# define pthread_detach GC_pthread_detach # define pthread_detach GC_pthread_detach
#ifndef GC_DARWIN_THREADS
# define pthread_sigmask GC_pthread_sigmask
# define dlopen GC_dlopen # define dlopen GC_dlopen
#endif
#endif /* GC_xxxxx_THREADS */ #endif /* GC_xxxxx_THREADS */
......
...@@ -29,14 +29,21 @@ ...@@ -29,14 +29,21 @@
# include "gc.h" # include "gc.h"
# endif # endif
#ifdef __cplusplus
extern "C" {
#endif
typedef GC_word * GC_bitmap; typedef GC_word * GC_bitmap;
/* The least significant bit of the first word is one if */ /* The least significant bit of the first word is one if */
/* the first word in the object may be a pointer. */ /* the first word in the object may be a pointer. */
# define GC_WORDSZ (8*sizeof(GC_word))
# define GC_get_bit(bm, index) \ # define GC_get_bit(bm, index) \
(((bm)[divWORDSZ(index)] >> modWORDSZ(index)) & 1) (((bm)[index/GC_WORDSZ] >> (index%GC_WORDSZ)) & 1)
# define GC_set_bit(bm, index) \ # define GC_set_bit(bm, index) \
(bm)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index) (bm)[index/GC_WORDSZ] |= ((GC_word)1 << (index%GC_WORDSZ))
# define GC_WORD_OFFSET(t, f) (offsetof(t,f)/sizeof(GC_word))
# define GC_WORD_LEN(t) (sizeof(t)/ sizeof(GC_word))
# define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ-1)/GC_WORDSZ)
typedef GC_word GC_descr; typedef GC_word GC_descr;
...@@ -57,6 +64,16 @@ GC_API GC_descr GC_make_descriptor GC_PROTO((GC_bitmap bm, size_t len)); ...@@ -57,6 +64,16 @@ GC_API GC_descr GC_make_descriptor GC_PROTO((GC_bitmap bm, size_t len));
/* is intended to be called once per type, not once */ /* is intended to be called once per type, not once */
/* per allocation. */ /* per allocation. */
/* It is possible to generate a descriptor for a C type T with */
/* word aligned pointer fields f1, f2, ... as follows: */
/* */
/* GC_descr T_descr; */
/* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0}; */
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1)); */
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2)); */
/* ... */
/* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T)); */
GC_API GC_PTR GC_malloc_explicitly_typed GC_API GC_PTR GC_malloc_explicitly_typed
GC_PROTO((size_t size_in_bytes, GC_descr d)); GC_PROTO((size_t size_in_bytes, GC_descr d));
/* Allocate an object whose layout is described by d. */ /* Allocate an object whose layout is described by d. */
...@@ -79,15 +96,18 @@ GC_API GC_PTR GC_calloc_explicitly_typed ...@@ -79,15 +96,18 @@ GC_API GC_PTR GC_calloc_explicitly_typed
/* Returned object is cleared. */ /* Returned object is cleared. */
#ifdef GC_DEBUG #ifdef GC_DEBUG
# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes) # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes)
# define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes) # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes)
#else #else
# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) \ # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
GC_malloc_explicitly_typed(bytes, d) GC_malloc_explicitly_typed(bytes, d)
# define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) \ # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
GC_calloc_explicitly_typed(n, bytes, d) GC_calloc_explicitly_typed(n, bytes, d)
#endif /* !GC_DEBUG */ #endif /* !GC_DEBUG */
#ifdef __cplusplus
} /* matches extern "C" */
#endif
#endif /* _GC_TYPED_H */ #endif /* _GC_TYPED_H */
...@@ -64,6 +64,14 @@ ...@@ -64,6 +64,14 @@
#endif #endif
#endif #endif
/* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */
/* you should probably really use gc_allocator.h instead. */
#if defined (__GNUC__) && \
(__GNUC > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1)))
# define simple_alloc __simple_alloc
#endif
#define GC_ALLOC_H #define GC_ALLOC_H
......
...@@ -115,16 +115,24 @@ typedef struct { ...@@ -115,16 +115,24 @@ typedef struct {
#ifdef SHORT_DBG_HDRS #ifdef SHORT_DBG_HDRS
# define DEBUG_BYTES (sizeof (oh)) # define DEBUG_BYTES (sizeof (oh))
# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES
#else #else
/* Add space for END_FLAG, but use any extra space that was already */ /* Add space for END_FLAG, but use any extra space that was already */
/* added to catch off-the-end pointers. */ /* added to catch off-the-end pointers. */
# define DEBUG_BYTES (sizeof (oh) + sizeof (word) - EXTRA_BYTES) /* For uncollectable objects, the extra byte is not added. */
# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word))
# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)
#endif #endif
#define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh)) #define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh))
/* Round bytes to words without adding extra byte at end. */ /* 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) #define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
/* ADD_CALL_CHAIN stores a (partial) call chain into an object */
/* header. It may be called with or without the allocation */
/* lock. */
/* PRINT_CALL_CHAIN prints the call chain stored in an object */
/* to stderr. It requires that we do not hold the lock. */
#ifdef SAVE_CALL_CHAIN #ifdef SAVE_CALL_CHAIN
# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) # define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci)
# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
......
...@@ -70,7 +70,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */ ...@@ -70,7 +70,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
#define ADVANCE(p, hhdr, source) \ #define ADVANCE(p, hhdr, source) \
{ \ { \
hdr * new_hdr = GC_invalid_header; \ hdr * new_hdr = GC_invalid_header; \
p = GC_FIND_START(p, hhdr, &new_hdr, (word)source); \ p = GC_find_start(p, hhdr, &new_hdr); \
hhdr = new_hdr; \ hhdr = new_hdr; \
} }
......
...@@ -137,7 +137,7 @@ extern mse * GC_mark_stack; ...@@ -137,7 +137,7 @@ extern mse * GC_mark_stack;
#ifdef __STDC__ #ifdef __STDC__
# ifdef PRINT_BLACK_LIST # ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p,
ptr_t source); word source);
# else # else
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p); ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif # endif
...@@ -145,7 +145,7 @@ extern mse * GC_mark_stack; ...@@ -145,7 +145,7 @@ extern mse * GC_mark_stack;
ptr_t GC_find_start(); ptr_t GC_find_start();
#endif #endif
mse *GC_signal_mark_stack_overflow(mse *msp); mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp));
# ifdef GATHERSTATS # ifdef GATHERSTATS
# define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz) # define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
...@@ -174,14 +174,6 @@ mse *GC_signal_mark_stack_overflow(mse *msp); ...@@ -174,14 +174,6 @@ mse *GC_signal_mark_stack_overflow(mse *msp);
} \ } \
} }
#ifdef PRINT_BLACK_LIST
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p, source)
#else
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p)
#endif
/* Push the contents of current onto the mark stack if it is a valid */ /* Push the contents of current onto the mark stack if it is a valid */
/* ptr to a currently unmarked object. Mark it. */ /* ptr to a currently unmarked object. Mark it. */
/* If we assumed a standard-conforming compiler, we could probably */ /* If we assumed a standard-conforming compiler, we could probably */
...@@ -195,8 +187,7 @@ mse *GC_signal_mark_stack_overflow(mse *msp); ...@@ -195,8 +187,7 @@ mse *GC_signal_mark_stack_overflow(mse *msp);
GET_HDR(my_current, my_hhdr); \ GET_HDR(my_current, my_hhdr); \
if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \ if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
hdr * new_hdr = GC_invalid_header; \ hdr * new_hdr = GC_invalid_header; \
my_current = GC_FIND_START(my_current, my_hhdr, \ my_current = GC_find_start(my_current, my_hhdr, &new_hdr); \
&new_hdr, (word)source); \
my_hhdr = new_hdr; \ my_hhdr = new_hdr; \
} \ } \
PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \ PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
...@@ -290,21 +281,39 @@ exit_label: ; \ ...@@ -290,21 +281,39 @@ exit_label: ; \
/* /*
* Push a single value onto mark stack. Mark from the object pointed to by p. * Push a single value onto mark stack. Mark from the object pointed to by p.
* Invoke FIXUP_POINTER(p) before any further processing.
* P is considered valid even if it is an interior pointer. * P is considered valid even if it is an interior pointer.
* Previously marked objects are not pushed. Hence we make progress even * Previously marked objects are not pushed. Hence we make progress even
* if the mark stack overflows. * if the mark stack overflows.
*/ */
# define GC_PUSH_ONE_STACK(p, source) \
if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ # if NEED_FIXUP_POINTER
/* Try both the raw version and the fixed up one. */
# define GC_PUSH_ONE_STACK(p, source) \
if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
&& (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
PUSH_ONE_CHECKED_STACK(p, source); \ PUSH_ONE_CHECKED_STACK(p, source); \
} } \
FIXUP_POINTER(p); \
if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
&& (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
PUSH_ONE_CHECKED_STACK(p, source); \
}
# else /* !NEED_FIXUP_POINTER */
# define GC_PUSH_ONE_STACK(p, source) \
if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
&& (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
PUSH_ONE_CHECKED_STACK(p, source); \
}
# endif
/* /*
* As above, but interior pointer recognition as for * As above, but interior pointer recognition as for
* normal for heap pointers. * normal for heap pointers.
*/ */
# define GC_PUSH_ONE_HEAP(p,source) \ # define GC_PUSH_ONE_HEAP(p,source) \
FIXUP_POINTER(p); \
if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
&& (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
GC_mark_stack_top = GC_mark_and_push( \ GC_mark_stack_top = GC_mark_and_push( \
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
# define DETACHED 2 /* Thread is intended to be detached. */ # define DETACHED 2 /* Thread is intended to be detached. */
# define CLIENT_OWNS_STACK 4 # define CLIENT_OWNS_STACK 4
/* Stack was supplied by client. */ /* Stack was supplied by client. */
# define SUSPENDED 8 /* Currently suspended. */ # define SUSPNDED 8 /* Currently suspended. */
/* SUSPENDED is used insystem header. */
ptr_t stack; ptr_t stack;
size_t stack_size; size_t stack_size;
cond_t join_cv; cond_t join_cv;
......
...@@ -85,7 +85,7 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) { ...@@ -85,7 +85,7 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) {
unsigned hash_val = CACHE_HASH(qtid); unsigned hash_val = CACHE_HASH(qtid);
tse * volatile * entry_ptr = key -> cache + hash_val; tse * volatile * entry_ptr = key -> cache + hash_val;
tse * entry = *entry_ptr; /* Must be loaded only once. */ tse * entry = *entry_ptr; /* Must be loaded only once. */
if (entry -> qtid == qtid) { if (EXPECT(entry -> qtid == qtid, 1)) {
GC_ASSERT(entry -> thread == pthread_self()); GC_ASSERT(entry -> thread == pthread_self());
return entry -> value; return entry -> value;
} }
......
...@@ -74,7 +74,8 @@ asm static void PushMacRegisters() ...@@ -74,7 +74,8 @@ asm static void PushMacRegisters()
/* on your architecture. Run the test_setjmp program to see whether */ /* on your architecture. Run the test_setjmp program to see whether */
/* there is any chance it will work. */ /* there is any chance it will work. */
#ifndef USE_GENERIC_PUSH_REGS #if !defined(USE_GENERIC_PUSH_REGS) && !defined(USE_ASM_PUSH_REGS)
#undef HAVE_PUSH_REGS
void GC_push_regs() void GC_push_regs()
{ {
# ifdef RT # ifdef RT
...@@ -91,6 +92,7 @@ void GC_push_regs() ...@@ -91,6 +92,7 @@ void GC_push_regs()
asm("pushl r8"); asm("calls $1,_GC_push_one"); asm("pushl r8"); asm("calls $1,_GC_push_one");
asm("pushl r7"); asm("calls $1,_GC_push_one"); asm("pushl r7"); asm("calls $1,_GC_push_one");
asm("pushl r6"); asm("calls $1,_GC_push_one"); asm("pushl r6"); asm("calls $1,_GC_push_one");
# define HAVE_PUSH_REGS
# endif # endif
# if defined(M68K) && (defined(SUNOS4) || defined(NEXT)) # if defined(M68K) && (defined(SUNOS4) || defined(NEXT))
/* M68K SUNOS - could be replaced by generic code */ /* M68K SUNOS - could be replaced by generic code */
...@@ -113,6 +115,7 @@ void GC_push_regs() ...@@ -113,6 +115,7 @@ void GC_push_regs()
asm("movl d7,sp@"); asm("jbsr _GC_push_one"); asm("movl d7,sp@"); asm("jbsr _GC_push_one");
asm("addqw #0x4,sp"); /* put stack back where it was */ asm("addqw #0x4,sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif # endif
# if defined(M68K) && defined(HP) # if defined(M68K) && defined(HP)
...@@ -135,6 +138,7 @@ void GC_push_regs() ...@@ -135,6 +138,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one"); asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */ asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif /* M68K HP */ # endif /* M68K HP */
# if defined(M68K) && defined(AMIGA) # if defined(M68K) && defined(AMIGA)
...@@ -158,6 +162,7 @@ void GC_push_regs() ...@@ -158,6 +162,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one"); asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */ asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# else /* !__GNUC__ */ # else /* !__GNUC__ */
GC_push_one(getreg(REG_A2)); GC_push_one(getreg(REG_A2));
GC_push_one(getreg(REG_A3)); GC_push_one(getreg(REG_A3));
...@@ -174,6 +179,7 @@ void GC_push_regs() ...@@ -174,6 +179,7 @@ void GC_push_regs()
GC_push_one(getreg(REG_D5)); GC_push_one(getreg(REG_D5));
GC_push_one(getreg(REG_D6)); GC_push_one(getreg(REG_D6));
GC_push_one(getreg(REG_D7)); GC_push_one(getreg(REG_D7));
# define HAVE_PUSH_REGS
# endif /* !__GNUC__ */ # endif /* !__GNUC__ */
# endif /* AMIGA */ # endif /* AMIGA */
...@@ -196,10 +202,12 @@ void GC_push_regs() ...@@ -196,10 +202,12 @@ void GC_push_regs()
PushMacReg(d7); PushMacReg(d7);
add.w #4,sp ; fix stack. add.w #4,sp ; fix stack.
} }
# define HAVE_PUSH_REGS
# undef PushMacReg # undef PushMacReg
# endif /* THINK_C */ # endif /* THINK_C */
# if defined(__MWERKS__) # if defined(__MWERKS__)
PushMacRegisters(); PushMacRegisters();
# define HAVE_PUSH_REGS
# endif /* __MWERKS__ */ # endif /* __MWERKS__ */
# endif /* MACOS */ # endif /* MACOS */
...@@ -222,13 +230,15 @@ void GC_push_regs() ...@@ -222,13 +230,15 @@ void GC_push_regs()
asm("pushl %esi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %esi"); asm("call _GC_push_one"); asm("addl $4,%esp");
asm("pushl %edi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %edi"); asm("call _GC_push_one"); asm("addl $4,%esp");
asm("pushl %ebx"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %ebx"); asm("call _GC_push_one"); asm("addl $4,%esp");
# define HAVE_PUSH_REGS
# endif # endif
# if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \ # if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \
|| ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(NETBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(NETBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(OPENBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(OPENBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(HURD) && defined(__ELF__) ) || ( defined(I386) && defined(HURD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(DGUX) )
/* This is modified for Linux with ELF (Note: _ELF_ only) */ /* This is modified for Linux with ELF (Note: _ELF_ only) */
/* This section handles FreeBSD with ELF. */ /* This section handles FreeBSD with ELF. */
...@@ -243,6 +253,7 @@ void GC_push_regs() ...@@ -243,6 +253,7 @@ void GC_push_regs()
asm("pushl %esi; call GC_push_one; addl $4,%esp"); asm("pushl %esi; call GC_push_one; addl $4,%esp");
asm("pushl %edi; call GC_push_one; addl $4,%esp"); asm("pushl %edi; call GC_push_one; addl $4,%esp");
asm("pushl %ebx; call GC_push_one; addl $4,%esp"); asm("pushl %ebx; call GC_push_one; addl $4,%esp");
# define HAVE_PUSH_REGS
# endif # endif
# if ( defined(I386) && defined(BEOS) && defined(__ELF__) ) # if ( defined(I386) && defined(BEOS) && defined(__ELF__) )
...@@ -254,6 +265,7 @@ void GC_push_regs() ...@@ -254,6 +265,7 @@ void GC_push_regs()
asm("pushl %esi; call GC_push_one; addl $4,%esp"); asm("pushl %esi; call GC_push_one; addl $4,%esp");
asm("pushl %edi; call GC_push_one; addl $4,%esp"); asm("pushl %edi; call GC_push_one; addl $4,%esp");
asm("pushl %ebx; call GC_push_one; addl $4,%esp"); asm("pushl %ebx; call GC_push_one; addl $4,%esp");
# define HAVE_PUSH_REGS
# endif # endif
# if defined(I386) && defined(MSWIN32) && !defined(__MINGW32__) \ # if defined(I386) && defined(MSWIN32) && !defined(__MINGW32__) \
...@@ -280,6 +292,7 @@ void GC_push_regs() ...@@ -280,6 +292,7 @@ void GC_push_regs()
__asm push edi __asm push edi
__asm call GC_push_one __asm call GC_push_one
__asm add esp,4 __asm add esp,4
# define HAVE_PUSH_REGS
# endif # endif
# if defined(I386) && (defined(SVR4) || defined(SCO) || defined(SCO_ELF)) # if defined(I386) && (defined(SVR4) || defined(SCO) || defined(SCO_ELF))
...@@ -291,6 +304,7 @@ void GC_push_regs() ...@@ -291,6 +304,7 @@ void GC_push_regs()
asm("pushl %ebp"); asm("call GC_push_one"); asm("addl $4,%esp"); asm("pushl %ebp"); asm("call GC_push_one"); asm("addl $4,%esp");
asm("pushl %esi"); asm("call GC_push_one"); asm("addl $4,%esp"); asm("pushl %esi"); asm("call GC_push_one"); asm("addl $4,%esp");
asm("pushl %edi"); asm("call GC_push_one"); asm("addl $4,%esp"); asm("pushl %edi"); asm("call GC_push_one"); asm("addl $4,%esp");
# define HAVE_PUSH_REGS
# endif # endif
# ifdef NS32K # ifdef NS32K
...@@ -299,14 +313,12 @@ void GC_push_regs() ...@@ -299,14 +313,12 @@ void GC_push_regs()
asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
# define HAVE_PUSH_REGS
# endif # endif
# if defined(SPARC) # if defined(SPARC)
{ GC_save_regs_ret_val = GC_save_regs_in_stack();
word GC_save_regs_in_stack(); # define HAVE_PUSH_REGS
GC_save_regs_ret_val = GC_save_regs_in_stack();
}
# endif # endif
# ifdef RT # ifdef RT
...@@ -322,6 +334,7 @@ void GC_push_regs() ...@@ -322,6 +334,7 @@ void GC_push_regs()
asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */ asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */
asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */ asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */
asm("cas r11, r15, r0"); GC_push_one(TMP_SP); asm("cas r11, r15, r0"); GC_push_one(TMP_SP);
# define HAVE_PUSH_REGS
# endif # endif
# if defined(M68K) && defined(SYSV) # if defined(M68K) && defined(SYSV)
...@@ -345,6 +358,7 @@ void GC_push_regs() ...@@ -345,6 +358,7 @@ void GC_push_regs()
asm("movl %d7,%sp@"); asm("jbsr GC_push_one"); asm("movl %d7,%sp@"); asm("jbsr GC_push_one");
asm("addqw #0x4,%sp"); /* put stack back where it was */ asm("addqw #0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# else /* !__GNUC__*/ # else /* !__GNUC__*/
asm("subq.w &0x4,%sp"); /* allocate word on top of stack */ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */
...@@ -362,6 +376,7 @@ void GC_push_regs() ...@@ -362,6 +376,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */ asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif /* !__GNUC__ */ # endif /* !__GNUC__ */
# endif /* M68K/SYSV */ # endif /* M68K/SYSV */
...@@ -371,21 +386,19 @@ void GC_push_regs() ...@@ -371,21 +386,19 @@ void GC_push_regs()
extern int *__libc_stack_end; extern int *__libc_stack_end;
GC_push_all_stack (sp, __libc_stack_end); GC_push_all_stack (sp, __libc_stack_end);
# define HAVE_PUSH_REGS
/* Isn't this redundant with the code to push the stack? */
} }
# endif # endif
/* other machines... */ /* other machines... */
# if !defined(M68K) && !defined(VAX) && !defined(RT) # if !defined(HAVE_PUSH_REGS)
# if !defined(SPARC) && !defined(I386) && !defined(NS32K) --> We just generated an empty GC_push_regs, which
# if !defined(POWERPC) && !defined(UTS4) --> is almost certainly broken. Try defining
# if !defined(PJ) && !(defined(MIPS) && defined(LINUX)) --> USE_GENERIC_PUSH_REGS instead.
--> bad news <--
# endif
# endif
# endif
# endif # endif
} }
#endif /* !USE_GENERIC_PUSH_REGS */ #endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
#if defined(USE_GENERIC_PUSH_REGS) #if defined(USE_GENERIC_PUSH_REGS)
void GC_generic_push_regs(cold_gc_frame) void GC_generic_push_regs(cold_gc_frame)
...@@ -427,8 +440,6 @@ ptr_t cold_gc_frame; ...@@ -427,8 +440,6 @@ ptr_t cold_gc_frame;
/* needed on IA64, since some non-windowed registers are */ /* needed on IA64, since some non-windowed registers are */
/* preserved. */ /* preserved. */
{ {
word GC_save_regs_in_stack();
GC_save_regs_ret_val = GC_save_regs_in_stack(); GC_save_regs_ret_val = GC_save_regs_in_stack();
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */ /* On IA64 gcc, could use __builtin_ia64_flushrs() and */
/* __builtin_ia64_flushrs(). The latter will be done */ /* __builtin_ia64_flushrs(). The latter will be done */
...@@ -445,7 +456,7 @@ ptr_t cold_gc_frame; ...@@ -445,7 +456,7 @@ ptr_t cold_gc_frame;
/* the stack. Return sp. */ /* the stack. Return sp. */
# ifdef SPARC # ifdef SPARC
asm(" .seg \"text\""); asm(" .seg \"text\"");
# ifdef SVR4 # if defined(SVR4) || defined(NETBSD)
asm(" .globl GC_save_regs_in_stack"); asm(" .globl GC_save_regs_in_stack");
asm("GC_save_regs_in_stack:"); asm("GC_save_regs_in_stack:");
asm(" .type GC_save_regs_in_stack,#function"); asm(" .type GC_save_regs_in_stack,#function");
......
...@@ -182,6 +182,7 @@ register int k; ...@@ -182,6 +182,7 @@ register int k;
ptr_t result; ptr_t result;
DCL_LOCK_STATE; DCL_LOCK_STATE;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS(); GC_INVOKE_FINALIZERS();
if (SMALL_OBJ(lb)) { if (SMALL_OBJ(lb)) {
DISABLE_SIGNALS(); DISABLE_SIGNALS();
...@@ -294,6 +295,11 @@ DCL_LOCK_STATE; ...@@ -294,6 +295,11 @@ DCL_LOCK_STATE;
return(GENERAL_MALLOC((word)lb, NORMAL)); return(GENERAL_MALLOC((word)lb, NORMAL));
} }
/* See above comment on signals. */ /* See above comment on signals. */
GC_ASSERT(0 == obj_link(op)
|| (word)obj_link(op)
<= (word)GC_greatest_plausible_heap_addr
&& (word)obj_link(op)
>= (word)GC_least_plausible_heap_addr);
*opp = obj_link(op); *opp = obj_link(op);
obj_link(op) = 0; obj_link(op) = 0;
GC_words_allocd += lw; GC_words_allocd += lw;
...@@ -338,6 +344,7 @@ DCL_LOCK_STATE; ...@@ -338,6 +344,7 @@ DCL_LOCK_STATE;
return((GC_PTR)REDIRECT_MALLOC(n*lb)); return((GC_PTR)REDIRECT_MALLOC(n*lb));
} }
#ifndef strdup
# include <string.h> # include <string.h>
# ifdef __STDC__ # ifdef __STDC__
char *strdup(const char *s) char *strdup(const char *s)
...@@ -346,11 +353,16 @@ DCL_LOCK_STATE; ...@@ -346,11 +353,16 @@ DCL_LOCK_STATE;
char *s; char *s;
# endif # endif
{ {
size_t len = strlen + 1; size_t len = strlen(s) + 1;
char * result = ((char *)REDIRECT_MALLOC(len+1)); char * result = ((char *)REDIRECT_MALLOC(len+1));
BCOPY(s, result, len+1); BCOPY(s, result, len+1);
return result; return result;
} }
#endif /* !defined(strdup) */
/* If strdup is macro defined, we assume that it actually calls malloc, */
/* and thus the right thing will happen even without overriding it. */
/* This seems to be true on most Linux systems. */
# endif /* REDIRECT_MALLOC */ # endif /* REDIRECT_MALLOC */
/* Explicitly deallocate an object p. */ /* Explicitly deallocate an object p. */
...@@ -373,6 +385,7 @@ DCL_LOCK_STATE; ...@@ -373,6 +385,7 @@ DCL_LOCK_STATE;
/* Required by ANSI. It's not my fault ... */ /* Required by ANSI. It's not my fault ... */
h = HBLKPTR(p); h = HBLKPTR(p);
hhdr = HDR(h); hhdr = HDR(h);
GC_ASSERT(GC_base(p) == p);
# if defined(REDIRECT_MALLOC) && \ # if defined(REDIRECT_MALLOC) && \
(defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \ (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
|| defined(__MINGW32__)) /* Should this be MSWIN32 in general? */ || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
...@@ -454,7 +467,10 @@ void GC_free_inner(GC_PTR p) ...@@ -454,7 +467,10 @@ void GC_free_inner(GC_PTR p)
} }
#endif /* THREADS */ #endif /* THREADS */
# ifdef REDIRECT_MALLOC # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
# define REDIRECT_FREE GC_free
# endif
# ifdef REDIRECT_FREE
# ifdef __STDC__ # ifdef __STDC__
void free(GC_PTR p) void free(GC_PTR p)
# else # else
...@@ -463,7 +479,7 @@ void GC_free_inner(GC_PTR p) ...@@ -463,7 +479,7 @@ void GC_free_inner(GC_PTR p)
# endif # endif
{ {
# ifndef IGNORE_FREE # ifndef IGNORE_FREE
GC_free(p); REDIRECT_FREE(p);
# endif # endif
} }
# endif /* REDIRECT_MALLOC */ # endif /* REDIRECT_MALLOC */
...@@ -142,7 +142,11 @@ int obj_kind; ...@@ -142,7 +142,11 @@ int obj_kind;
} }
} }
# if defined(REDIRECT_MALLOC) || defined(REDIRECT_REALLOC) # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC)
# define REDIRECT_REALLOC GC_realloc
# endif
# ifdef REDIRECT_REALLOC
# ifdef __STDC__ # ifdef __STDC__
GC_PTR realloc(GC_PTR p, size_t lb) GC_PTR realloc(GC_PTR p, size_t lb)
# else # else
...@@ -151,13 +155,9 @@ int obj_kind; ...@@ -151,13 +155,9 @@ int obj_kind;
size_t lb; size_t lb;
# endif # endif
{ {
# ifdef REDIRECT_REALLOC return(REDIRECT_REALLOC(p, lb));
return(REDIRECT_REALLOC(p, lb));
# else
return(GC_realloc(p, lb));
# endif
} }
# endif /* REDIRECT_MALLOC */ # endif /* REDIRECT_REALLOC */
/* The same thing, except caller does not hold allocation lock. */ /* The same thing, except caller does not hold allocation lock. */
...@@ -177,6 +177,7 @@ register int k; ...@@ -177,6 +177,7 @@ register int k;
lw = ROUNDED_UP_WORDS(lb); lw = ROUNDED_UP_WORDS(lb);
n_blocks = OBJ_SZ_TO_BLOCKS(lw); n_blocks = OBJ_SZ_TO_BLOCKS(lw);
init = GC_obj_kinds[k].ok_init; init = GC_obj_kinds[k].ok_init;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS(); GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS(); DISABLE_SIGNALS();
LOCK(); LOCK();
...@@ -286,6 +287,7 @@ register struct obj_kind * kind = GC_obj_kinds + k; ...@@ -286,6 +287,7 @@ register struct obj_kind * kind = GC_obj_kinds + k;
register ptr_t op; register ptr_t op;
DCL_LOCK_STATE; DCL_LOCK_STATE;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS(); GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS(); DISABLE_SIGNALS();
LOCK(); LOCK();
...@@ -354,6 +356,7 @@ DCL_LOCK_STATE; ...@@ -354,6 +356,7 @@ DCL_LOCK_STATE;
return; return;
} }
lw = ALIGNED_WORDS(lb); lw = ALIGNED_WORDS(lb);
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS(); GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS(); DISABLE_SIGNALS();
LOCK(); LOCK();
...@@ -375,6 +378,7 @@ DCL_LOCK_STATE; ...@@ -375,6 +378,7 @@ DCL_LOCK_STATE;
while ((hbp = *rlh) != 0) { while ((hbp = *rlh) != 0) {
hhdr = HDR(hbp); hhdr = HDR(hbp);
*rlh = hhdr -> hb_next; *rlh = hhdr -> hb_next;
hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
# ifdef PARALLEL_MARK # ifdef PARALLEL_MARK
{ {
signed_word my_words_allocd_tmp = GC_words_allocd_tmp; signed_word my_words_allocd_tmp = GC_words_allocd_tmp;
...@@ -575,6 +579,44 @@ DCL_LOCK_STATE; ...@@ -575,6 +579,44 @@ DCL_LOCK_STATE;
} }
} }
#ifdef __STDC__
/* Not well tested nor integrated. */
/* Debug version is tricky and currently missing. */
#include <limits.h>
GC_PTR GC_memalign(size_t align, size_t lb)
{
size_t new_lb;
size_t offset;
ptr_t result;
# ifdef ALIGN_DOUBLE
if (align <= WORDS_TO_BYTES(2) && lb > align) return GC_malloc(lb);
# endif
if (align <= WORDS_TO_BYTES(1)) return GC_malloc(lb);
if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) {
if (align > HBLKSIZE) return GC_oom_fn(LONG_MAX-1024) /* Fail */;
return GC_malloc(lb <= HBLKSIZE? HBLKSIZE : lb);
/* Will be HBLKSIZE aligned. */
}
/* We could also try to make sure that the real rounded-up object size */
/* is a multiple of align. That would be correct up to HBLKSIZE. */
new_lb = lb + align - 1;
result = GC_malloc(new_lb);
offset = (word)result % align;
if (offset != 0) {
offset = align - offset;
if (!GC_all_interior_pointers) {
if (offset >= VALID_OFFSET_SZ) return GC_malloc(HBLKSIZE);
GC_register_displacement(offset);
}
}
result = (GC_PTR) ((ptr_t)result + offset);
GC_ASSERT((word)result % align == 0);
return result;
}
#endif
# ifdef ATOMIC_UNCOLLECTABLE # ifdef ATOMIC_UNCOLLECTABLE
/* Allocate lb bytes of pointerfree, untraced, uncollectable data */ /* Allocate lb bytes of pointerfree, untraced, uncollectable data */
/* This is normally roughly equivalent to the system malloc. */ /* This is normally roughly equivalent to the system malloc. */
......
...@@ -275,33 +275,72 @@ void GC_clear_roots GC_PROTO((void)) ...@@ -275,33 +275,72 @@ void GC_clear_roots GC_PROTO((void))
} }
/* Internal use only; lock held. */ /* Internal use only; lock held. */
static void GC_remove_root_at_pos(i)
int i;
{
GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start);
GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start;
GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end;
GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp;
n_root_sets--;
}
#if !defined(MSWIN32) && !defined(MSWINCE)
static void GC_rebuild_root_index()
{
register int i;
for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
for (i = 0; i < n_root_sets; i++)
add_roots_to_index(GC_static_roots + i);
}
#endif
/* Internal use only; lock held. */
void GC_remove_tmp_roots() void GC_remove_tmp_roots()
{ {
register int i; register int i;
for (i = 0; i < n_root_sets; ) { for (i = 0; i < n_root_sets; ) {
if (GC_static_roots[i].r_tmp) { if (GC_static_roots[i].r_tmp) {
GC_root_size -= GC_remove_root_at_pos(i);
(GC_static_roots[i].r_end - GC_static_roots[i].r_start);
GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start;
GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end;
GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp;
n_root_sets--;
} else { } else {
i++; i++;
}
} }
# if !defined(MSWIN32) && !defined(MSWINCE)
{
register int i;
for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
for (i = 0; i < n_root_sets; i++)
add_roots_to_index(GC_static_roots + i);
} }
# endif #if !defined(MSWIN32) && !defined(MSWINCE)
GC_rebuild_root_index();
#endif
}
#if !defined(MSWIN32) && !defined(MSWINCE)
void GC_remove_roots(b, e)
char * b; char * e;
{
DCL_LOCK_STATE;
DISABLE_SIGNALS();
LOCK();
GC_remove_roots_inner(b, e);
UNLOCK();
ENABLE_SIGNALS();
}
/* Should only be called when the lock is held */
void GC_remove_roots_inner(b,e)
char * b; char * e;
{
int i;
for (i = 0; i < n_root_sets; ) {
if (GC_static_roots[i].r_start >= (ptr_t)b && GC_static_roots[i].r_end <= (ptr_t)e) {
GC_remove_root_at_pos(i);
} else {
i++;
}
}
GC_rebuild_root_index();
} }
#endif /* !defined(MSWIN32) && !defined(MSWINCE) */
#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) #if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)
/* Workaround for the OS mapping and unmapping behind our back: */ /* Workaround for the OS mapping and unmapping behind our back: */
...@@ -573,8 +612,11 @@ ptr_t cold_gc_frame; ...@@ -573,8 +612,11 @@ ptr_t cold_gc_frame;
/* Mark thread local free lists, even if their mark */ /* Mark thread local free lists, even if their mark */
/* descriptor excludes the link field. */ /* descriptor excludes the link field. */
/* If the world is not stopped, this is unsafe. It is */
/* also unnecessary, since we will do this again with the */
/* world stopped. */
# ifdef THREAD_LOCAL_ALLOC # ifdef THREAD_LOCAL_ALLOC
GC_mark_thread_local_free_lists(); if (GC_world_stopped) GC_mark_thread_local_free_lists();
# endif # endif
/* /*
......
#include <sys/regdef.h> #include <sys/regdef.h>
#include <sys/asm.h> #include <sys/asm.h>
/* This file must be preprocessed. But the SGI assembler always does */
/* that. Furthermore, a generic preprocessor won't do, since some of */
/* the SGI-supplied include files rely on behavior of the MIPS */
/* assembler. Hence we treat and name this file as though it required */
/* no preprocessing. */
# define call_push(x) move $4,x; jal GC_push_one # define call_push(x) move $4,x; jal GC_push_one
......
.text
.set linkageArea,24
.set params,4
.set alignment,4
.set spaceToSave,linkageArea+params+alignment
.set spaceToSave8,spaceToSave+8
; Mark from machine registers that are saved by C compiler
.globl _GC_push_regs
_GC_push_regs:
; PROLOG
mflr r0 ; get return address
stw r0,8(r1) ; save return address
stwu r1,-spaceToSave(r1) ; skip over caller save area
;
mr r3,r2 ; mark from r2. Well Im not really sure
; that this is necessary or even the right
; thing to do - at least it doesnt harm...
; According to Apples docs it points to
; the direct data area, whatever that is...
bl L_GC_push_one$stub
mr r3,r13 ; mark from r13-r31
bl L_GC_push_one$stub
mr r3,r14
bl L_GC_push_one$stub
mr r3,r15
bl L_GC_push_one$stub
mr r3,r16
bl L_GC_push_one$stub
mr r3,r17
bl L_GC_push_one$stub
mr r3,r18
bl L_GC_push_one$stub
mr r3,r19
bl L_GC_push_one$stub
mr r3,r20
bl L_GC_push_one$stub
mr r3,r21
bl L_GC_push_one$stub
mr r3,r22
bl L_GC_push_one$stub
mr r3,r23
bl L_GC_push_one$stub
mr r3,r24
bl L_GC_push_one$stub
mr r3,r25
bl L_GC_push_one$stub
mr r3,r26
bl L_GC_push_one$stub
mr r3,r27
bl L_GC_push_one$stub
mr r3,r28
bl L_GC_push_one$stub
mr r3,r29
bl L_GC_push_one$stub
mr r3,r30
bl L_GC_push_one$stub
mr r3,r31
bl L_GC_push_one$stub
; EPILOG
lwz r0,spaceToSave8(r1) ; get return address back
mtlr r0 ; reset link register
addic r1,r1,spaceToSave ; restore stack pointer
blr
.data
.picsymbol_stub
L_GC_push_one$stub:
.indirect_symbol _GC_push_one
mflr r0
bcl 20,31,L0$_GC_push_one
L0$_GC_push_one:
mflr r11
addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
mtlr r0
lwz r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
mtctr r12
addi r11,r11,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
bctr
.data
.lazy_symbol_pointer
L_GC_push_one$lazy_ptr:
.indirect_symbol _GC_push_one
.long dyld_stub_binding_helper
.non_lazy_symbol_pointer
L_GC_push_one$non_lazy_ptr:
.indirect_symbol _GC_push_one
.long 0
...@@ -79,7 +79,7 @@ void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR)) ...@@ -79,7 +79,7 @@ void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
return(p); return(p);
} }
sz = WORDS_TO_BYTES(hhdr -> hb_sz); sz = WORDS_TO_BYTES(hhdr -> hb_sz);
if (sz > WORDS_TO_BYTES(MAXOBJSZ)) { if (sz > MAXOBJBYTES) {
base = (ptr_t)HBLKPTR(p); base = (ptr_t)HBLKPTR(p);
limit = base + sz; limit = base + sz;
if ((ptr_t)p >= limit) { if ((ptr_t)p >= limit) {
...@@ -165,7 +165,7 @@ void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) = ...@@ -165,7 +165,7 @@ void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) =
pdispl = HBLKDISPL(p); pdispl = HBLKDISPL(p);
map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl); map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
if (map_entry == OBJ_INVALID if (map_entry == OBJ_INVALID
|| sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) { || sz > MAXOBJBYTES && (ptr_t)p >= (ptr_t)h + sz) {
goto fail; goto fail;
} }
return(p); return(p);
......
...@@ -27,23 +27,61 @@ signed_word GC_mem_found = 0; ...@@ -27,23 +27,61 @@ signed_word GC_mem_found = 0;
/* nonzero. */ /* nonzero. */
#endif /* PARALLEL_MARK */ #endif /* PARALLEL_MARK */
static void report_leak(p, sz) /* We defer printing of leaked objects until we're done with the GC */
ptr_t p; /* cycle, since the routine for printing objects needs to run outside */
word sz; /* the collector, e.g. without the allocation lock. */
#define MAX_LEAKED 40
ptr_t GC_leaked[MAX_LEAKED];
unsigned GC_n_leaked = 0;
GC_bool GC_have_errors = FALSE;
void GC_add_leaked(leaked)
ptr_t leaked;
{ {
if (HDR(p) -> hb_obj_kind == PTRFREE) { if (GC_n_leaked < MAX_LEAKED) {
GC_err_printf0("Leaked atomic object at "); GC_have_errors = TRUE;
} else { GC_leaked[GC_n_leaked++] = leaked;
GC_err_printf0("Leaked composite object at "); /* Make sure it's not reclaimed this cycle */
GC_set_mark_bit(leaked);
} }
GC_print_heap_obj(p);
GC_err_printf0("\n");
} }
static GC_bool printing_errors = FALSE;
/* Print all objects on the list after printing any smashed objs. */
/* Clear both lists. */
void GC_print_all_errors ()
{
unsigned i;
LOCK();
if (printing_errors) {
UNLOCK();
return;
}
printing_errors = TRUE;
UNLOCK();
if (GC_debugging_started) GC_print_all_smashed();
for (i = 0; i < GC_n_leaked; ++i) {
ptr_t p = GC_leaked[i];
if (HDR(p) -> hb_obj_kind == PTRFREE) {
GC_err_printf0("Leaked atomic object at ");
} else {
GC_err_printf0("Leaked composite object at ");
}
GC_print_heap_obj(p);
GC_err_printf0("\n");
GC_free(p);
GC_leaked[i] = 0;
}
GC_n_leaked = 0;
printing_errors = FALSE;
}
# define FOUND_FREE(hblk, word_no) \ # define FOUND_FREE(hblk, word_no) \
{ \ { \
report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \ GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
HDR(hblk) -> hb_sz); \
} }
/* /*
...@@ -866,7 +904,7 @@ void GC_print_block_list() ...@@ -866,7 +904,7 @@ void GC_print_block_list()
* Clear *flp. * Clear *flp.
* This must be done before dropping a list of free gcj-style objects, * This must be done before dropping a list of free gcj-style objects,
* since may otherwise end up with dangling "descriptor" pointers. * since may otherwise end up with dangling "descriptor" pointers.
* It may help for other pointer-containg objects. * It may help for other pointer-containing objects.
*/ */
void GC_clear_fl_links(flp) void GC_clear_fl_links(flp)
ptr_t *flp; ptr_t *flp;
......
...@@ -13,9 +13,8 @@ ...@@ -13,9 +13,8 @@
/* /*
* Support code for Solaris threads. Provides functionality we wish Sun * Support code for Solaris threads. Provides functionality we wish Sun
* had provided. Relies on some information we probably shouldn't rely on. * had provided. Relies on some information we probably shouldn't rely on.
* Modified Peter C. for Solaris Posix Threads. * Modified by Peter C. for Solaris Posix Threads.
*/ */
/* Boehm, September 14, 1994 4:44 pm PDT */
# if defined(GC_SOLARIS_PTHREADS) # if defined(GC_SOLARIS_PTHREADS)
# include "private/gc_priv.h" # include "private/gc_priv.h"
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
# include <unistd.h> # include <unistd.h>
# include <errno.h> # include <errno.h>
#ifdef HANDLE_FORK
--> Not yet supported. Try porting the code from linux_threads.c.
#endif
/* /*
* This is the default size of the LWP arrays. If there are more LWPs * This is the default size of the LWP arrays. If there are more LWPs
* than this when a stop-the-world GC happens, set_max_lwps will be * than this when a stop-the-world GC happens, set_max_lwps will be
...@@ -361,7 +365,7 @@ static void restart_all_lwps() ...@@ -361,7 +365,7 @@ static void restart_all_lwps()
sizeof (prgregset_t)) != 0) { sizeof (prgregset_t)) != 0) {
int j; int j;
for(j = 0; j < NGREG; j++) for(j = 0; j < NPRGREG; j++)
{ {
GC_printf3("%i: %x -> %x\n", j, GC_printf3("%i: %x -> %x\n", j,
GC_lwp_registers[i][j], GC_lwp_registers[i][j],
...@@ -821,7 +825,7 @@ int GC_thr_suspend(thread_t target_thread) ...@@ -821,7 +825,7 @@ int GC_thr_suspend(thread_t target_thread)
if (result == 0) { if (result == 0) {
t = GC_lookup_thread(target_thread); t = GC_lookup_thread(target_thread);
if (t == 0) ABORT("thread unknown to GC"); if (t == 0) ABORT("thread unknown to GC");
t -> flags |= SUSPENDED; t -> flags |= SUSPNDED;
} }
UNLOCK(); UNLOCK();
return(result); return(result);
...@@ -837,7 +841,7 @@ int GC_thr_continue(thread_t target_thread) ...@@ -837,7 +841,7 @@ int GC_thr_continue(thread_t target_thread)
if (result == 0) { if (result == 0) {
t = GC_lookup_thread(target_thread); t = GC_lookup_thread(target_thread);
if (t == 0) ABORT("thread unknown to GC"); if (t == 0) ABORT("thread unknown to GC");
t -> flags &= ~SUSPENDED; t -> flags &= ~SUSPNDED;
} }
UNLOCK(); UNLOCK();
return(result); return(result);
...@@ -923,7 +927,7 @@ GC_thr_create(void *stack_base, size_t stack_size, ...@@ -923,7 +927,7 @@ GC_thr_create(void *stack_base, size_t stack_size,
my_flags |= CLIENT_OWNS_STACK; my_flags |= CLIENT_OWNS_STACK;
} }
if (flags & THR_DETACHED) my_flags |= DETACHED; if (flags & THR_DETACHED) my_flags |= DETACHED;
if (flags & THR_SUSPENDED) my_flags |= SUSPENDED; if (flags & THR_SUSPENDED) my_flags |= SUSPNDED;
result = thr_create(stack, stack_size, start_routine, result = thr_create(stack, stack_size, start_routine,
arg, flags & ~THR_DETACHED, &my_new_thread); arg, flags & ~THR_DETACHED, &my_new_thread);
if (result == 0) { if (result == 0) {
......
...@@ -37,7 +37,7 @@ loop: ...@@ -37,7 +37,7 @@ loop:
stx %g0,[%o3] ! *(long *)p = 0 stx %g0,[%o3] ! *(long *)p = 0
cmp %o3,%o1 cmp %o3,%o1
bgu,pt %xcc, loop ! if (p > limit) goto loop bgu,pt %xcc, loop ! if (p > limit) goto loop
add %o3,-8,%o3 ! p -= 8 (delay slot) add %o3,-8,%o3 ! p -= 8 (delay slot)
retl retl
mov %o2,%sp ! Restore sp., delay slot mov %o2,%sp ! Restore sp., delay slot
#else /* 32 bit SPARC */ #else /* 32 bit SPARC */
......
...@@ -28,7 +28,10 @@ few minutes to complete. ...@@ -28,7 +28,10 @@ few minutes to complete.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __GNUC__ #define USE_STD_ALLOCATOR
#ifdef USE_STD_ALLOCATOR
# include "gc_allocator.h"
#elif __GNUC__
# include "new_gc_alloc.h" # include "new_gc_alloc.h"
#else #else
# include "gc_alloc.h" # include "gc_alloc.h"
...@@ -189,25 +192,32 @@ int APIENTRY WinMain( ...@@ -189,25 +192,32 @@ int APIENTRY WinMain(
# endif # endif
#endif #endif
GC_init();
# if defined(MACOS) // MacOS # if defined(MACOS) // MacOS
char* argv_[] = {"test_cpp", "10"}; // doesn't char* argv_[] = {"test_cpp", "10"}; // doesn't
argv = argv_; // have a argv = argv_; // have a
argc = sizeof(argv_)/sizeof(argv_[0]); // commandline argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
# endif # endif
int i, iters, n; int i, iters, n;
# if !defined(MACOS) # ifdef USE_STD_ALLOCATOR
int *x = gc_allocator<int>().allocate(1);
int **xptr = traceable_allocator<int *>().allocate(1);
# else
# ifdef __GNUC__ # ifdef __GNUC__
int *x = (int *)gc_alloc::allocate(sizeof(int)); int *x = (int *)gc_alloc::allocate(sizeof(int));
# else # else
int *x = (int *)alloc::allocate(sizeof(int)); int *x = (int *)alloc::allocate(sizeof(int));
# endif # endif
# endif
*x = 29; *x = 29;
x -= 3; # ifdef USE_STD_ALLOCATOR
*xptr = x;
x = 0;
# endif # endif
if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) { if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
GC_printf0( "usage: test_cpp number-of-iterations\n" ); GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
exit( 1 );} n = 10;}
for (iters = 1; iters <= n; iters++) { for (iters = 1; iters <= n; iters++) {
GC_printf1( "Starting iteration %d\n", iters ); GC_printf1( "Starting iteration %d\n", iters );
...@@ -268,9 +278,10 @@ int APIENTRY WinMain( ...@@ -268,9 +278,10 @@ int APIENTRY WinMain(
D::Test(); D::Test();
F::Test();} F::Test();}
# if !defined(__GNUC__) && !defined(MACOS) # ifdef USE_STD_ALLOCATOR
my_assert (29 == x[3]); x = *xptr;
# endif # endif
my_assert (29 == x[0]);
GC_printf0( "The test appears to have succeeded.\n" ); GC_printf0( "The test appears to have succeeded.\n" );
return( 0 );} return( 0 );}
......
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
int main() int main()
{ {
# if defined(GC_USE_LD_WRAP) # if defined(GC_USE_LD_WRAP)
printf("-Wl,--wrap -Wl,read -Wl,--wrap -Wl,dlopen " printf("-Wl,--wrap -Wl,dlopen "
"-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join " "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join "
"-Wl,--wrap -Wl,pthread_detach " "-Wl,--wrap -Wl,pthread_detach "
"-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n"); "-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
# endif # endif
# if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \ # if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \
|| defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS) || defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS) \
|| defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
printf("-lpthread\n"); printf("-lpthread\n");
# endif # endif
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
...@@ -19,6 +20,17 @@ int main() ...@@ -19,6 +20,17 @@ int main()
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) # if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
printf("-lthread -ldl\n"); printf("-lthread -ldl\n");
# endif # endif
# if defined(GC_WIN32_THREADS) && defined(CYGWIN32)
printf("-lpthread\n");
# endif
# if defined(GC_OSF1_THREADS)
printf("-pthread -lrt"); /* DOB: must be -pthread, not -lpthread */
# endif
/* You need GCC 3.0.3 to build this one! */
/* DG/UX native gcc doesnt know what "-pthread" is */
# if defined(GC_DGUX386_THREADS)
printf("-ldl -pthread\n");
# endif
return 0; return 0;
} }
...@@ -437,6 +437,7 @@ void GC_init_explicit_typing() ...@@ -437,6 +437,7 @@ void GC_init_explicit_typing()
for (; bm != 0; bm >>= 1, current_p++) { for (; bm != 0; bm >>= 1, current_p++) {
if (bm & 1) { if (bm & 1) {
current = *current_p; current = *current_p;
FIXUP_POINTER(current);
if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) { if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) {
PUSH_CONTENTS((ptr_t)current, mark_stack_ptr, PUSH_CONTENTS((ptr_t)current, mark_stack_ptr,
mark_stack_limit, current_p, exit1); mark_stack_limit, current_p, exit1);
...@@ -674,9 +675,9 @@ DCL_LOCK_STATE; ...@@ -674,9 +675,9 @@ DCL_LOCK_STATE;
if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) { if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
FASTUNLOCK(); FASTUNLOCK();
op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind); op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
if (0 == op) return(0); if (0 == op) return 0;
# ifdef MERGE_SIZES # ifdef MERGE_SIZES
lw = GC_size_map[lb]; /* May have been uninitialized. */ lw = GC_size_map[lb]; /* May have been uninitialized. */
# endif # endif
} else { } else {
*opp = obj_link(op); *opp = obj_link(op);
...@@ -720,7 +721,7 @@ DCL_LOCK_STATE; ...@@ -720,7 +721,7 @@ DCL_LOCK_STATE;
FASTUNLOCK(); FASTUNLOCK();
op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
# ifdef MERGE_SIZES # ifdef MERGE_SIZES
lw = GC_size_map[lb]; /* May have been uninitialized. */ lw = GC_size_map[lb]; /* May have been uninitialized. */
# endif # endif
} else { } else {
*opp = obj_link(op); *opp = obj_link(op);
......
#define GC_VERSION_MAJOR 6 /* The version here should match that in configure/configure.in */
#define GC_VERSION_MINOR 1 /* Eventually this one may become unnecessary. For now we need */
#define GC_ALPHA_VERSION 3 /* 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
#ifndef GC_NOT_ALPHA
# define GC_NOT_ALPHA 0xff # define GC_NOT_ALPHA 0xff
#endif
#if defined(GC_VERSION_MAJOR)
# if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR || \
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.
# endif
#else
# define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
# define GC_VERSION_MINOR GC_TMP_VERSION_MINOR
# define GC_ALPHA_VERSION GC_TMP_ALPHA_VERSION
#endif
#ifndef GC_NO_VERSION_VAR #ifndef GC_NO_VERSION_VAR
unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_ALPHA_VERSION); unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_TMP_ALPHA_VERSION);
#endif /* GC_NO_VERSION_VAR */ #endif /* GC_NO_VERSION_VAR */
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