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
# For Borland 5.0, replace bc45 by bc5.
# Makefile for Borland C++ 5.5 on NT
# If you have the Borland assembler, remove "-DUSE_GENERIC"
#
bc= c:\bc45
bc= c:\Borland\BCC55
bcbin= $(bc)\bin
bclib= $(bc)\lib
bcinclude= $(bc)\include
gcinclude1 = $(bc)\gc6.2\include
gcinclude2 = $(bc)\gc6.2\cord
cc= $(bcbin)\bcc32
rc= $(bcbin)\brc32
lib= $(bcbin)\tlib
link= $(bcbin)\tlink32
cflags= -R -v -vi -H -H=gc.csm -I$(bcinclude);cord -L$(bclib) \
link= $(bcbin)\ilink32
cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \
-w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0
#defines= -DSILENT
defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC
defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
.c.obj:
$(cc) @&&|
......@@ -39,11 +41,11 @@ OBJS= $(XXXOBJS:XXX=)
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)
-del gc.lib
tlib $* @&&|
del gc.lib
$(lib) $* @&&|
$(XXXOBJS:XXX=+)
|
......@@ -52,7 +54,7 @@ gctest.exe: 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.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \
......@@ -63,7 +65,7 @@ cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \
|
$(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
copy gc_cpp.cc gc_cpp.cpp
......@@ -71,7 +73,7 @@ gc_cpp.cpp: gc_cpp.cc
test_cpp.cpp: tests\test_cpp.cc
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) @&&|
$(cflags) -W -e$* test_cpp.obj gc.lib
|
......@@ -79,4 +81,8 @@ test_cpp.exe: test_cpp.obj gc_cpp.h gc.h gc.lib
scratch:
-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>
* configure.host: Only use +ESdbgasm when using the HPUX native
......
......@@ -74,7 +74,7 @@
// implementations, and it sometimes has a significant performance
// impact. However, it is dangerous for many not-quite-ANSI C
// 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.
// See gc_cpp.h for details. No effect on the C part of the collector.
// This is defined implicitly in a few environments.
......
......@@ -72,7 +72,7 @@
// implementations, and it sometimes has a significant performance
// impact. However, it is dangerous for many not-quite-ANSI C
// 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.
// See gc_cpp.h for details. No effect on the C part of the collector.
// This is defined implicitly in a few environments.
......
......@@ -18,15 +18,23 @@ MULTICLEAN = true
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 \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c irix_threads.c \
linux_threads.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c \
malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c win32_threads.c
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 \
mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
EXTRA_GC_SOURCES = alpha_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 \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
......@@ -63,7 +71,9 @@ TESTS = gctest
## FIXME: relies on internal code generated by automake.
all_objs = @addobjs@ $(libgcjgc_la_OBJECTS)
$(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.
.s.lo:
......
......@@ -152,7 +152,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIO
# currently probably works only with Linux.
CXXFLAGS= $(CFLAGS) -DOPERATOR_NEW_ARRAY
CXXFLAGS= $(CFLAGS) -DGC_OPERATOR_NEW_ARRAY
AR= ar
RANLIB= ranlib
......@@ -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
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 \
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 \
include/private/gc_hdrs.h include/private/gc_priv.h \
include/private/gcconfig.h include/private/gc_mark.h \
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 \
include/private/solaris_threads.h include/gc_backptr.h \
hpux_test_and_clear.s include/gc_gcj.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)
OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
......@@ -284,16 +284,16 @@ liblinuxgc.so: $(OBJS) dyn_load.o
gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo
ln liblinuxgc.so libgc.so
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)
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_darwin_mach_dep.s $(UTILS)
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 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 POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_macosx_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 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 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_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
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......@@ -66,9 +66,11 @@ target_triplet = @target@
AR = @AR@
AS = @AS@
CC = @CC@
CFLAGS = @CFLAGS@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CXXINCLUDES = @CXXINCLUDES@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
......@@ -89,7 +91,10 @@ RANLIB = @RANLIB@
STRIP = @STRIP@
THREADLIBS = @THREADLIBS@
VERSION = @VERSION@
addincludes = @addincludes@
addlibs = @addlibs@
addobjs = @addobjs@
addtests = @addtests@
gc_basedir = @gc_basedir@
mkinstalldirs = @mkinstalldirs@
target_all = @target_all@
......@@ -109,17 +114,21 @@ MULTIDO = true
MULTICLEAN = true
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 \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c irix_threads.c \
linux_threads.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c \
malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c win32_threads.c
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 \
mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
EXTRA_GC_SOURCES = alpha_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 \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
......@@ -213,24 +222,53 @@ DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \
dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \
irix_threads.lo linux_threads.lo malloc.lo mallocx.lo mark.lo \
mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo \
ptr_chck.lo real_malloc.lo reclaim.lo solaris_pthreads.lo \
solaris_threads.lo specific.lo stubborn.lo typd_mlc.lo backgraph.lo \
win32_threads.lo
@POWERPC_DARWIN_FALSE@libgcjgc_la_OBJECTS = allchblk.lo alloc.lo \
@POWERPC_DARWIN_FALSE@blacklst.lo checksums.lo dbg_mlc.lo dyn_load.lo \
@POWERPC_DARWIN_FALSE@finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \
@POWERPC_DARWIN_FALSE@aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \
@POWERPC_DARWIN_FALSE@mark_rts.lo misc.lo new_hblk.lo obj_map.lo \
@POWERPC_DARWIN_FALSE@os_dep.lo pcr_interface.lo ptr_chck.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_OBJECTS = allchblk.lo alloc.lo blacklst.lo \
checksums.lo dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
headers.lo irix_threads.lo linux_threads.lo malloc.lo mallocx.lo \
mark.lo mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo \
pcr_interface.lo ptr_chck.lo real_malloc.lo reclaim.lo \
solaris_pthreads.lo solaris_threads.lo specific.lo stubborn.lo \
typd_mlc.lo backgraph.lo win32_threads.lo
@POWERPC_DARWIN_FALSE@libgcjgc_convenience_la_OBJECTS = allchblk.lo \
@POWERPC_DARWIN_FALSE@alloc.lo blacklst.lo checksums.lo dbg_mlc.lo \
@POWERPC_DARWIN_FALSE@dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
@POWERPC_DARWIN_FALSE@headers.lo aix_irix_threads.lo malloc.lo \
@POWERPC_DARWIN_FALSE@mallocx.lo mark.lo mark_rts.lo misc.lo \
@POWERPC_DARWIN_FALSE@new_hblk.lo obj_map.lo os_dep.lo pcr_interface.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)
gctest_DEPENDENCIES = ./libgcjgc.la
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \
......@@ -368,7 +406,7 @@ maintainer-clean-recursive:
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
test "$$subdir" != "." || dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
......@@ -598,7 +636,9 @@ mostlyclean distclean maintainer-clean
test.o: tests/test.c
$(COMPILE) -c $(srcdir)/tests/test.c
$(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:
$(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
......
......@@ -47,12 +47,16 @@ GC_bool GC_use_entire_heap = 0;
struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 };
#ifndef USE_MUNMAP
word GC_free_bytes[N_HBLK_FLS+1] = { 0 };
/* Number of free bytes on each list. */
/* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */
/* > 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;
int n;
{
......@@ -583,11 +587,11 @@ int n;
if (!GC_use_entire_heap
&& size_avail != size_needed
&& USED_HEAP_SIZE >= GC_requested_heapsize
&& !GC_incremental && GC_should_collect()) {
&& !TRUE_INCREMENTAL && GC_should_collect()) {
# ifdef USE_MUNMAP
continue;
# 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 */
/* and split. Assuming a steady state, that should */
/* be safe. It means that we can use the full */
......@@ -595,6 +599,12 @@ int n;
if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) {
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 */
}
/* 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 */
GC_bool GC_need_full_gc = FALSE;
/* 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;
char * GC_copyright[] =
......@@ -160,7 +167,7 @@ static word min_words_allocd()
+ (GC_large_free_bytes >> 2)
/* use a bit more of large empty heap */
+ total_root_size);
if (GC_incremental) {
if (TRUE_INCREMENTAL) {
return scan_size / (2 * GC_free_space_divisor);
} else {
return scan_size / GC_free_space_divisor;
......@@ -182,7 +189,8 @@ word GC_adj_words_allocd()
/* managed object should not alter result, assuming the client */
/* is playing by the rules. */
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) {
result = GC_words_allocd;
/* probably client bug or unfortunate scheduling */
......@@ -250,7 +258,6 @@ void GC_maybe_gc()
if (GC_should_collect()) {
if (!GC_incremental) {
GC_notify_full_gc();
GC_gcollect_inner();
n_partial_gcs = 0;
return;
......@@ -302,10 +309,14 @@ void GC_maybe_gc()
/*
* 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.
* Return TRUE if we successfully completed the collection.
*/
GC_bool GC_try_to_collect_inner(stop_func)
GC_stop_func stop_func;
{
# ifdef CONDPRINT
CLOCK_TYPE start_time, current_time;
# endif
if (GC_dont_gc) return FALSE;
if (GC_incremental && GC_collection_in_progress()) {
# ifdef CONDPRINT
......@@ -320,8 +331,10 @@ GC_stop_func stop_func;
GC_collect_a_little_inner(1);
}
}
if (stop_func == GC_never_stop_func) GC_notify_full_gc();
# ifdef CONDPRINT
if (GC_print_stats) {
if (GC_print_stats) GET_TIME(start_time);
GC_printf2(
"Initiating full world-stop collection %lu after %ld allocd bytes\n",
(unsigned long) GC_gc_no+1,
......@@ -360,6 +373,13 @@ GC_stop_func stop_func;
return(FALSE);
}
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);
}
......@@ -430,6 +450,7 @@ int GC_collect_a_little GC_PROTO(())
result = (int)GC_collection_in_progress();
UNLOCK();
ENABLE_SIGNALS();
if (!result && GC_debugging_started) GC_print_all_smashed();
return(result);
}
......@@ -448,16 +469,17 @@ GC_stop_func stop_func;
CLOCK_TYPE start_time, current_time;
# endif
# if defined(REGISTER_LIBRARIES_EARLY)
GC_cond_register_dynamic_libraries();
# endif
STOP_WORLD();
# ifdef PRINTTIMES
GET_TIME(start_time);
# endif
# if defined(CONDPRINT) && !defined(PRINTTIMES)
if (GC_print_stats) GET_TIME(start_time);
# endif
# if defined(REGISTER_LIBRARIES_EARLY)
GC_cond_register_dynamic_libraries();
# endif
STOP_WORLD();
IF_THREADS(GC_world_stopped = TRUE);
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf1("--> Marking for collection %lu ",
......@@ -488,6 +510,7 @@ GC_stop_func stop_func;
}
# endif
GC_deficit = i; /* Give the mutator a chance. */
IF_THREADS(GC_world_stopped = FALSE);
START_WORLD();
return(FALSE);
}
......@@ -521,6 +544,8 @@ GC_stop_func stop_func;
(*GC_check_heap)();
}
IF_THREADS(GC_world_stopped = FALSE);
START_WORLD();
# ifdef PRINTTIMES
GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n",
......@@ -534,7 +559,6 @@ GC_stop_func stop_func;
}
# endif
# endif
START_WORLD();
return(TRUE);
}
......@@ -611,6 +635,7 @@ void GC_finish_collection()
GC_print_address_map();
}
# endif
COND_DUMP;
if (GC_find_leak) {
/* Mark all objects on the free list. All objects should be */
/* marked when we're done. */
......@@ -707,6 +732,7 @@ void GC_finish_collection()
GC_words_allocd = 0;
GC_words_wasted = 0;
GC_mem_freed = 0;
GC_finalizer_mem_freed = 0;
# ifdef USE_MUNMAP
GC_unmap_old();
......@@ -730,6 +756,7 @@ void GC_finish_collection()
int result;
DCL_LOCK_STATE;
if (GC_debugging_started) GC_print_all_smashed();
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
......@@ -741,14 +768,17 @@ void GC_finish_collection()
EXIT_GC();
UNLOCK();
ENABLE_SIGNALS();
if(result) GC_INVOKE_FINALIZERS();
if(result) {
if (GC_debugging_started) GC_print_all_smashed();
GC_INVOKE_FINALIZERS();
}
return(result);
}
void GC_gcollect GC_PROTO(())
{
GC_notify_full_gc();
(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. */
......@@ -950,7 +980,6 @@ GC_bool ignore_off_page;
{
if (!GC_incremental && !GC_dont_gc &&
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
GC_notify_full_gc();
GC_gcollect_inner();
} else {
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
......@@ -975,7 +1004,6 @@ GC_bool ignore_off_page;
&& !GC_expand_hp_inner(needed_blocks)) {
if (GC_fail_count++ < GC_max_retries) {
WARN("Out of Memory! Trying to continue ...\n", 0);
GC_notify_full_gc();
GC_gcollect_inner();
} else {
# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
......@@ -1005,14 +1033,15 @@ ptr_t GC_allocobj(sz, kind)
word sz;
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);
while (*flh == 0) {
ENTER_GC();
/* 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 */
GC_continue_reclaim(sz, kind);
EXIT_GC();
......@@ -1021,13 +1050,21 @@ int kind;
}
if (*flh == 0) {
ENTER_GC();
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();
return(0);
}
}
EXIT_GC();
}
}
/* Successful allocation; reset failure count. */
GC_fail_count = 0;
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 @@
# host The configuration host
# host_cpu The configuration host CPU
# target_optspace --enable-target-optspace ("yes", "no", "")
# GCC should be "yes" if using gcc
# It sets the following shell variables:
# gc_cflags Special CFLAGS to use when building
gc_cflags=""
# We should set -fexceptions if we are using gcc and might be used
# inside something like gcj. This is the zeroth approximation:
case "$host" in
*-*-linux* )
gc_cflags=-fexceptions
;;
if test :"$GCC": = :yes: ; then
gc_cflags="${gc_cflags} -fexceptions"
else
case "$host" in
hppa*-*-hpux* )
if test $GCC != "yes" ; then
gc_cflags=+ESdbgasm
if test :$GCC: != :"yes": ; then
gc_cflags="${gc_flags} +ESdbgasm"
fi
# :TODO: actaully we should check using Autoconf if
# the compiler supports this option.
;;
esac
esac
fi
case "${target_optspace}:${host}" in
yes:*)
......@@ -48,7 +54,7 @@ esac
case "${host}" in
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
THREADS=posix
THREADLIBS=-lpthread
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(_REENTRANT)
if test "${enable_parallel_mark}"; then
if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK)
fi
AC_DEFINE(THREAD_LOCAL_ALLOC)
......@@ -85,6 +85,10 @@ case "$THREADS" in
AC_DEFINE(GC_LINUX_THREADS)
AC_DEFINE(_REENTRANT)
;;
*-*-aix*)
AC_DEFINE(GC_AIX_THREADS)
AC_DEFINE(_REENTRANT)
;;
*-*-hpux*)
AC_MSG_WARN("Only HP/UX 11 threads are supported.")
AC_DEFINE(GC_HPUX_THREADS)
......@@ -109,16 +113,52 @@ case "$THREADS" in
AC_DEFINE(GC_IRIX_THREADS)
;;
*-*-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
;;
win32)
AC_DEFINE(GC_WIN32_THREADS)
dnl Wine getenv may not return NULL for missing entry
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
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)
AC_MSG_ERROR(thread package $THREADS not yet supported)
......@@ -129,7 +169,22 @@ case "$THREADS" in
esac
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)
target_all=libgcjgc.la
......@@ -147,6 +202,9 @@ TARGET_ECOS="$with_ecos"
)
addobjs=
addlibs=
addincludes=
addtests=
CXXINCLUDES=
case "$TARGET_ECOS" in
no)
......@@ -157,21 +215,46 @@ case "$TARGET_ECOS" in
addobjs="$addobjs ecos.lo"
;;
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(INCLUDES)
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=
case "$host" in
alpha*-*-openbsd*)
machdep="alpha_mach_dep.lo"
if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled)
AM_DISABLE_SHARED
fi
;;
alpha*-*-*)
alpha*-*-linux*)
machdep="alpha_mach_dep.lo"
;;
i?86-*-solaris2.[[89]]*)
......@@ -185,12 +268,17 @@ case "$host" in
mips-dec-ultrix*)
machdep="mips_ultrix_mach-dep.lo"
;;
mips-nec-sysv*|mips-unknown-sysv*)
;;
mips*-*-linux*)
;;
mips-*-*)
machdep="mips_sgi_mach_dep.lo"
AC_DEFINE(NO_EXECUTE_PERMISSION)
;;
sparc-*-netbsd*)
machdep="sparc_netbsd_mach_dep.lo"
;;
sparc-sun-solaris2.3*)
machdep="sparc_mach_dep.lo"
AC_DEFINE(SUNOS53_SHARED_LIB)
......@@ -203,16 +291,65 @@ case "$host" in
;;
esac
if test x"$machdep" = x; then
AC_MSG_RESULT($machdep)
machdep="mach_dep.lo"
fi
addobjs="$addobjs $machdep"
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 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
sparc-sun-solaris2*)
sparc-sun-solaris2*|*aix*)
if test "$GCC" = yes; then
AC_MSG_RESULT(yes)
new_CFLAGS=
for i in $CFLAGS; do
case "$i" in
......@@ -224,8 +361,11 @@ case "$host" in
esac
done
CFLAGS="$new_CFLAGS"
else
AC_MSG_RESULT(no)
fi
;;
*) AC_MSG_RESULT(no) ;;
esac
dnl We need to override the top-level CFLAGS. This is how we do it.
......@@ -267,6 +407,9 @@ AC_ARG_ENABLE(full-debug,
AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
AC_DEFINE(SAVE_CALL_COUNT, 8)
;;
i[3456]86-*-dgux*)
AC_DEFINE(MAKE_BACK_GRAPH)
;;
esac ]
fi)
......
......@@ -219,7 +219,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
result->len = result_len;
result->left = x;
result->right = y;
if (depth > MAX_DEPTH) {
if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
return((CORD) result);
......@@ -260,8 +260,12 @@ CORD CORD_cat(CORD x, CORD y)
result->len = result_len;
result->left = x;
result->right = y;
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)
if (width == NONE && prec == NONE) {
register char c;
c = va_arg(args, int);
c = (char)va_arg(args, int);
CORD_ec_append(result, c);
goto done;
}
......@@ -255,12 +255,18 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
/* Use standard sprintf to perform conversion */
{
register char * buf;
va_list vsprintf_args = args;
/* The above does not appear to be sanctioned */
/* by the ANSI C standard. */
va_list vsprintf_args;
int max_size = 0;
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 (prec == VARIABLE) prec = va_arg(args, int);
if (width != NONE) max_size = width;
......
......@@ -249,7 +249,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
case IDM_HELPABOUT:
if( DialogBox( hInstance, "ABOUTBOX",
hwnd, lpfnAboutBox ) );
hwnd, lpfnAboutBox ) )
InvalidateRect( hwnd, NULL, TRUE );
return( 0 );
case IDM_HELPCONTENTS:
......
......@@ -60,7 +60,7 @@ ptr_t p;
# include <stdlib.h>
# if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \
|| defined(HPUX) || defined(IRIX) || defined(OSF1)
|| defined(HPUX) || defined(IRIX5) || defined(OSF1)
# define RANDOM() random()
# else
# define RANDOM() (long)rand()
......@@ -228,6 +228,8 @@ ptr_t p;
#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. */
/* Assumes we don't hold allocation lock. */
ptr_t GC_store_debug_info(p, sz, string, integer)
......@@ -243,6 +245,8 @@ word integer;
/* But that's expensive. And this way things should only appear */
/* inconsistent while we're in the handler. */
LOCK();
GC_ASSERT(GC_size(p) >= sizeof(oh) + sz);
GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz)));
# ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif
......@@ -275,6 +279,8 @@ word integer;
/* There is some argument that we should disable signals here. */
/* But that's expensive. And this way things should only appear */
/* 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
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif
......@@ -324,10 +330,11 @@ ptr_t 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_puts(ohdr -> oh_string);
# 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
GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
(unsigned long)(ohdr -> oh_sz));
......@@ -342,6 +349,7 @@ ptr_t p;
ptr_t p;
# endif
{
GC_ASSERT(!I_HOLD_LOCK());
if (GC_HAS_DEBUG_INFO(p)) {
GC_print_obj(p);
} else {
......@@ -355,6 +363,7 @@ ptr_t p, clobbered_addr;
{
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,
(unsigned long)p);
if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
......@@ -376,14 +385,18 @@ ptr_t p, clobbered_addr;
void GC_check_heap_proc GC_PROTO((void));
void GC_print_all_smashed_proc GC_PROTO((void));
void GC_do_nothing() {}
void GC_start_debugging()
{
# ifndef SHORT_DBG_HDRS
GC_check_heap = GC_check_heap_proc;
GC_print_all_smashed = GC_print_all_smashed_proc;
# else
GC_check_heap = GC_do_nothing;
GC_print_all_smashed = GC_do_nothing;
# endif
GC_print_heap_obj = GC_debug_print_heap_obj_proc;
GC_debugging_started = TRUE;
......@@ -429,6 +442,62 @@ void GC_start_debugging()
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
/*
* An allocation function for internal use.
......@@ -447,7 +516,7 @@ void GC_start_debugging()
(unsigned long) lb);
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));
}
......@@ -461,7 +530,7 @@ void GC_start_debugging()
(unsigned long) lb);
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));
}
# endif
......@@ -592,7 +661,7 @@ GC_PTR p;
int i;
# endif
{
GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES);
GC_PTR result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
if (result == 0) {
GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
......@@ -618,7 +687,8 @@ GC_PTR p;
int i;
# 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) {
GC_err_printf1(
......@@ -774,6 +844,45 @@ void GC_debug_free_inner(GC_PTR p)
}
#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 */
/*ARGSUSED*/
# if defined(__STDC__) || defined(__cplusplus)
......@@ -802,11 +911,7 @@ void GC_debug_free_inner(GC_PTR p)
&& GC_HAS_DEBUG_INFO((ptr_t)p)) {
ptr_t clobbered = GC_check_annotated_obj((oh *)p);
if (clobbered != 0) {
GC_err_printf0(
"GC_check_heap_block: found smashed location at ");
GC_print_smashed_obj((ptr_t)p, clobbered);
}
if (clobbered != 0) GC_add_smashed(clobbered);
}
word_no += sz;
p += sz;
......@@ -819,9 +924,11 @@ void GC_debug_free_inner(GC_PTR p)
void GC_check_heap_proc()
{
# ifndef SMALL_CONFIG
if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
ABORT("Alignment problem: object header has inappropriate size\n");
}
# ifdef ALIGN_DOUBLE
GC_STATIC_ASSERT((sizeof(oh) & (2 * sizeof(word) - 1)) == 0);
# else
GC_STATIC_ASSERT((sizeof(oh) & (sizeof(word) - 1)) == 0);
# endif
# endif
GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
}
......@@ -908,7 +1015,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
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);
}
if (0 == fn) {
......@@ -940,7 +1047,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
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);
}
if (0 == fn) {
......@@ -973,7 +1080,7 @@ GC_PTR *ocd;
ptr_t base = GC_base(obj);
if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
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);
}
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) 1991-1996 by Xerox Corporation. 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
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
Copyright (c) 2001 by Red Hat Inc. All rights reserved.
The files config.guess and a few others are copyrighted by the Free
Software Foundation.
Several files supporting GNU-style builds are copyrighted by the Free
Software Foundation, and carry a different license from that given
below.
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
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
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
This is version 6.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
......@@ -228,10 +229,12 @@ and several of those are compatible with the collector.
or equivalent is supplied. Many of these have separate README.system
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),
Linux, IRIX 5&6, HP-PA, Win32 (not Win32S) and OSF/1 on DEC AXP machines.
On other machines we recommend that you do one of the following:
Linux, FreeBSD, NetBSD, IRIX 5&6, HP/UX, Win32 (not Win32S) and OSF/1
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).
2) Use static versions of the libraries.
......@@ -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
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.
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
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
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).
See README.darwin for the latest Darwin/MacOSX information.
......@@ -5,6 +5,8 @@ platforms.
GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed 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.
This may make it easier to debug, such a process, especially
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
by setting GC_quiet. On by default if the collector
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
maps for the process, to stderr on every GC. Useful for
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
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
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
warnings about allocations of very large blocks.
......@@ -62,6 +76,20 @@ GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects
of Conservative Garbage Collectors", POPL 2001, or
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,
depending on platform and collector configuration, this
may involve write protecting pieces of the heap to
......@@ -71,22 +99,20 @@ GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that,
Use with caution.
GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs.
This only has an effect if incremental collection is enabled.
If a collection requires appreciably more time than this,
the client will be restarted, and the collector will need
to do additional work to compensate. The special value
"999999" indicates that pause time is unlimited, and the
incremental collector will behave completely like a
simple generational collector. If the collector is
configured for parallel marking, and run on a multiprocessor,
incremental collection should 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:
This only has an effect if incremental collection is
enabled. If a collection requires appreciably more time
than this, the client will be restarted, and the collector
will need to do additional work to compensate. The
special value "999999" indicates that pause time is
unlimited, and the incremental collector will behave
completely like a simple generational collector. If
the collector is configured for parallel marking, and
run on a multiprocessor, incremental collection should
only be used with unlimited pause time.
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
pointer recognition.
......
See README.alpha for Linux on DEC AXP info.
This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K
and PowerPC are also integrated. They should behave similarly, except that
the PowerPC port lacks incremental GC support, and it is unknown to what
extent the Linux threads code is functional. See below for M68K specific
notes.
This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K, IA64,
SPARC, MIPS, Alpha and PowerPC are also integrated. They should behave
similarly, except that the PowerPC port lacks incremental GC support, and
it is unknown to what extent the Linux threads code is functional.
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
should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0".
The collector appears to work with Linux threads. We have seen
intermittent hangs in sem_wait. So far we have been unable to reproduce
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 collector appears to work reliably with Linux threads, but beware
of older versions of glibc and gdb.
The garbage collector uses SIGPWR and SIGXCPU if it is used with
Linux threads. These should not be touched by the client program.
......
......@@ -21,6 +21,13 @@ registrations are ignored, but not terribly quickly.)
pointers. And the VirtualQuery call has different semantics under
the two systems, and under different versions of win32s.)
Win32 applications compiled with some flavor of gcc currently behave
like win32s applications, in that dynamic library data segments are
not scanned. (Gcc does not directly support Microsoft's "structured
exception handling". It turns out that use of this feature is
unavoidable if you scan arbitrary memory segments obtained from
VirtualQuery.)
The collector test program "gctest" is linked as a GUI application,
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
......@@ -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.
To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC.
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
MAKEFILE. (Make sure that the CPU environment variable is defined
to be i386.) In order to use the gc_cpp.h C++ interface, all
client code should include gc_cpp.h.
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
collector was built as a static library (as it normally is in the
absence of thread support).
......@@ -64,7 +78,7 @@ absence of thread support).
For GNU-win32, use the regular makefile, possibly after uncommenting
the line "include Makefile.DLLs". The latter should be necessary only
if you want to package the collector as a DLL. The GNU-win32 port is
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
DATASTART and DATAEND in gcconfig.h.
......@@ -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.
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
important, otherwise resulting programs will not run.
......
......@@ -248,8 +248,12 @@ The <TT>hb_last_reclaimed</tt> field will identify the collection number
during which its block was last swept.
<LI> Verify that the offending object still has its correct contents at
this point.
The 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.
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. 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
register variable,
to the reclaimed object. Call <TT>GC_is_marked(q)</tt> for each object
......
......@@ -207,7 +207,8 @@ signed_word * log_size_ptr;
UNLOCK();
ENABLE_SIGNALS();
# 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) {
GC_finalization_failures++;
return(0);
......@@ -433,7 +434,8 @@ finalization_mark_proc * mp;
UNLOCK();
ENABLE_SIGNALS();
# 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) {
GC_finalization_failures++;
return;
......@@ -759,8 +761,9 @@ int GC_should_invoke_finalizers GC_PROTO((void))
/* Should be called without allocation lock. */
int GC_invoke_finalizers()
{
register struct finalizable_object * curr_fo;
register int count = 0;
struct finalizable_object * curr_fo;
int count = 0;
word mem_freed_before;
DCL_LOCK_STATE;
while (GC_finalize_now != 0) {
......@@ -768,6 +771,9 @@ int GC_invoke_finalizers()
DISABLE_SIGNALS();
LOCK();
# endif
if (count == 0) {
mem_freed_before = GC_mem_freed;
}
curr_fo = GC_finalize_now;
# ifdef THREADS
if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
......@@ -789,6 +795,11 @@ int GC_invoke_finalizers()
GC_free((GC_PTR)curr_fo);
# endif
}
if (count != 0 && mem_freed_before != GC_mem_freed) {
LOCK();
GC_finalizer_mem_freed += (GC_mem_freed - mem_freed_before);
UNLOCK();
}
return count;
}
......@@ -801,7 +812,9 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void))
if (GC_finalize_now == 0) return;
if (!GC_finalize_on_demand) {
(void) GC_invoke_finalizers();
# ifndef THREADS
GC_ASSERT(GC_finalize_now == 0);
# endif /* Otherwise GC can run concurrently and add more */
return;
}
if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0
......@@ -839,3 +852,17 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void))
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
#include "gc_cpp.h"
#ifndef _MSC_VER
/* In the Visual C++ case, we moved this into the header. */
void* operator new( size_t size ) {
return GC_MALLOC_UNCOLLECTABLE( size );}
void operator delete( void* obj ) {
GC_FREE( obj );}
#ifdef OPERATOR_NEW_ARRAY
#ifdef GC_OPERATOR_NEW_ARRAY
void* operator new[]( size_t size ) {
return GC_MALLOC_UNCOLLECTABLE( size );}
......@@ -42,8 +40,22 @@ void* operator new[]( size_t size ) {
void operator delete[]( void* 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 @@
/*
* 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
* dlopen. -HB
* dlopen. Of course this fails if the collector is in a dynamic
* library. -HB
*/
#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)
/* To support various threads pkgs, gc.h interposes on dlopen by */
......@@ -44,19 +46,14 @@
/* calls in either a multithreaded environment, or if the library */
/* initialization code allocates substantial amounts of GC'ed memory. */
/* But I don't know of a better solution. */
/* This can still deadlock if the client explicitly starts a GC */
/* during the dlopen. He shouldn't do that. */
static GC_bool disable_gc_for_dlopen()
static void disable_gc_for_dlopen()
{
GC_bool result;
LOCK();
result = GC_dont_gc;
while (GC_incremental && GC_collection_in_progress()) {
GC_collect_a_little_inner(1000);
}
GC_dont_gc = TRUE;
++GC_dont_gc;
UNLOCK();
return(result);
}
/* Redefine dlopen to guarantee mutual exclusion with */
......@@ -74,10 +71,9 @@
#endif
{
void * result;
GC_bool dont_gc_save;
# ifndef USE_PROC_FOR_LIBRARIES
dont_gc_save = disable_gc_for_dlopen();
disable_gc_for_dlopen();
# endif
# ifdef GC_USE_LD_WRAP
result = (void *)__real_dlopen(path, mode);
......@@ -85,7 +81,7 @@
result = dlopen(path, mode);
# endif
# ifndef USE_PROC_FOR_LIBRARIES
GC_dont_gc = dont_gc_save;
GC_enable(); /* undoes disable_gc_for_dlopen */
# endif
return(result);
}
......
......@@ -157,6 +157,7 @@ DCL_LOCK_STATE;
GC_words_allocd += lw;
}
*(void **)op = ptr_to_struct_containing_descr;
GC_ASSERT(((void **)op)[1] == 0);
UNLOCK();
} else {
LOCK();
......
......@@ -14,7 +14,7 @@ char ** envp;
if (strcmp(MACH_TYPE, argv[1]) != 0) return(0);
if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0
&& strcmp(OS_TYPE, argv[2]) != 0) return(0);
printf("^^^^Starting command^^^^\n");
fprintf(stderr, "^^^^Starting command^^^^\n");
fflush(stdout);
execvp(argv[3], argv+3);
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
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......@@ -66,9 +66,11 @@ target_triplet = @target@
AR = @AR@
AS = @AS@
CC = @CC@
CFLAGS = @CFLAGS@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CXXINCLUDES = @CXXINCLUDES@
DLLTOOL = @DLLTOOL@
EXEEXT = @EXEEXT@
......@@ -89,10 +91,15 @@ RANLIB = @RANLIB@
STRIP = @STRIP@
THREADLIBS = @THREADLIBS@
VERSION = @VERSION@
addincludes = @addincludes@
addlibs = @addlibs@
addobjs = @addobjs@
addtests = @addtests@
gc_basedir = @gc_basedir@
mkinstalldirs = @mkinstalldirs@
target_all = @target_all@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
AUTOMAKE_OPTIONS = foreign
......
......@@ -134,7 +134,9 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
#include "gc.h"
#ifndef THINK_CPLUS
#define _cdecl
# define GC_cdecl
#else
# define GC_cdecl _cdecl
#endif
#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
......@@ -159,12 +161,22 @@ enum GCPlacement {UseGC,
class gc {public:
inline void* operator new( size_t size );
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 );
# ifndef __BORLANDC__ /* Confuses the Borland compiler. */
inline void operator delete( void*, void* );
# endif
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[]( size_t size );
inline void* operator new[]( size_t size, GCPlacement gcp );
inline void* operator new[]( size_t size, void *p );
inline void operator delete[]( void* obj );
# ifndef __BORLANDC__
inline void gc::operator delete[]( void*, void* );
# endif
#endif /* GC_OPERATOR_NEW_ARRAY */
};
/*
......@@ -176,7 +188,7 @@ class gc_cleanup: virtual public gc {public:
inline gc_cleanup();
inline virtual ~gc_cleanup();
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
in the collected heap by default. When the collector discovers an
......@@ -211,7 +223,6 @@ inline void* operator new(
classes derived from "gc_cleanup" or containing members derived
from "gc_cleanup". */
#ifdef GC_OPERATOR_NEW_ARRAY
#ifdef _MSC_VER
/** This ensures that the system default operator new[] doesn't get
......@@ -220,42 +231,24 @@ inline void* operator new(
* There seems to be really redirect new in this environment without
* including this everywhere.
*/
inline void *operator new[]( size_t size )
{
return GC_MALLOC_UNCOLLECTABLE( size );
}
inline void operator delete[](void* obj)
{
GC_FREE(obj);
};
void *operator new[]( size_t size );
inline 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);
};
void* operator new( size_t size);
void operator delete(void* obj);
// This new operator is used by VC++ in case of Debug builds !
inline void* operator new( size_t size,
// 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
}
int nLine );
#endif /* _MSC_VER */
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[](
size_t size,
GCPlacement gcp,
......@@ -283,9 +276,15 @@ inline void* gc::operator new( size_t size, GCPlacement gcp ) {
else
return GC_MALLOC_UNCOLLECTABLE( size );}
inline void* gc::operator new( size_t size, void *p ) {
return p;}
inline void gc::operator delete( void* obj ) {
GC_FREE( obj );}
#ifndef __BORLANDC__
inline void gc::operator delete( void*, void* ) {}
#endif
#ifdef GC_OPERATOR_NEW_ARRAY
......@@ -295,14 +294,21 @@ inline void* gc::operator new[]( size_t size ) {
inline void* gc::operator new[]( size_t size, GCPlacement 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 ) {
gc::operator delete( obj );}
#ifndef __BORLANDC__
inline void gc::operator delete[]( void*, void* ) {}
#endif
#endif /* GC_OPERATOR_NEW_ARRAY */
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 ) {
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
......
......@@ -33,6 +33,9 @@
* -DTHREAD_LOCAL_ALLOC, which is currently supported only on Linux.
*
* 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
......
......@@ -129,7 +129,9 @@ extern GC_PTR GC_greatest_plausible_heap_addr;
/* be reserved for exceptional cases. That will ensure that */
/* performance of this call is not extremely performance critical. */
/* (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
GC_PROTO((GC_PTR obj,
struct GC_ms_entry * mark_stack_ptr,
......
......@@ -52,15 +52,30 @@
int GC_pthread_create(pthread_t *new_thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
#ifndef GC_DARWIN_THREADS
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_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_sigmask GC_pthread_sigmask
# define pthread_join GC_pthread_join
# define pthread_detach GC_pthread_detach
#ifndef GC_DARWIN_THREADS
# define pthread_sigmask GC_pthread_sigmask
# define dlopen GC_dlopen
#endif
#endif /* GC_xxxxx_THREADS */
......
......@@ -29,14 +29,21 @@
# include "gc.h"
# endif
#ifdef __cplusplus
extern "C" {
#endif
typedef GC_word * GC_bitmap;
/* The least significant bit of the first word is one if */
/* the first word in the object may be a pointer. */
# define GC_WORDSZ (8*sizeof(GC_word))
# 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) \
(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;
......@@ -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 */
/* 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_PROTO((size_t size_in_bytes, GC_descr d));
/* Allocate an object whose layout is described by d. */
......@@ -79,15 +96,18 @@ GC_API GC_PTR GC_calloc_explicitly_typed
/* Returned object is cleared. */
#ifdef GC_DEBUG
# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes)
# define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes)
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes)
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes)
#else
# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) \
# define 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)
#endif /* !GC_DEBUG */
#ifdef __cplusplus
} /* matches extern "C" */
#endif
#endif /* _GC_TYPED_H */
......@@ -64,6 +64,14 @@
#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
......
......@@ -115,16 +115,24 @@ typedef struct {
#ifdef SHORT_DBG_HDRS
# define DEBUG_BYTES (sizeof (oh))
# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES
#else
/* Add space for END_FLAG, but use any extra space that was already */
/* 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
#define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh))
/* Round bytes to words without adding extra byte at end. */
#define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
/* 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
# 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)
......
......@@ -70,7 +70,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
#define ADVANCE(p, hhdr, source) \
{ \
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; \
}
......
......@@ -137,7 +137,7 @@ extern mse * GC_mark_stack;
#ifdef __STDC__
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p,
ptr_t source);
word source);
# else
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif
......@@ -145,7 +145,7 @@ extern mse * GC_mark_stack;
ptr_t GC_find_start();
#endif
mse *GC_signal_mark_stack_overflow(mse *msp);
mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp));
# ifdef GATHERSTATS
# define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
......@@ -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 */
/* ptr to a currently unmarked object. Mark it. */
/* If we assumed a standard-conforming compiler, we could probably */
......@@ -195,8 +187,7 @@ mse *GC_signal_mark_stack_overflow(mse *msp);
GET_HDR(my_current, my_hhdr); \
if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
hdr * new_hdr = GC_invalid_header; \
my_current = GC_FIND_START(my_current, my_hhdr, \
&new_hdr, (word)source); \
my_current = GC_find_start(my_current, my_hhdr, &new_hdr); \
my_hhdr = new_hdr; \
} \
PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
......@@ -290,21 +281,39 @@ exit_label: ; \
/*
* 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.
* Previously marked objects are not pushed. Hence we make progress even
* if the mark stack overflows.
*/
# 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) { \
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
* normal for heap pointers.
*/
# define GC_PUSH_ONE_HEAP(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) { \
GC_mark_stack_top = GC_mark_and_push( \
......
......@@ -16,7 +16,8 @@
# define DETACHED 2 /* Thread is intended to be detached. */
# define CLIENT_OWNS_STACK 4
/* Stack was supplied by client. */
# define SUSPENDED 8 /* Currently suspended. */
# define SUSPNDED 8 /* Currently suspended. */
/* SUSPENDED is used insystem header. */
ptr_t stack;
size_t stack_size;
cond_t join_cv;
......
......@@ -85,7 +85,7 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) {
unsigned hash_val = CACHE_HASH(qtid);
tse * volatile * entry_ptr = key -> cache + hash_val;
tse * entry = *entry_ptr; /* Must be loaded only once. */
if (entry -> qtid == qtid) {
if (EXPECT(entry -> qtid == qtid, 1)) {
GC_ASSERT(entry -> thread == pthread_self());
return entry -> value;
}
......
......@@ -74,7 +74,8 @@ asm static void PushMacRegisters()
/* on your architecture. Run the test_setjmp program to see whether */
/* 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()
{
# ifdef RT
......@@ -91,6 +92,7 @@ void GC_push_regs()
asm("pushl r8"); asm("calls $1,_GC_push_one");
asm("pushl r7"); asm("calls $1,_GC_push_one");
asm("pushl r6"); asm("calls $1,_GC_push_one");
# define HAVE_PUSH_REGS
# endif
# if defined(M68K) && (defined(SUNOS4) || defined(NEXT))
/* M68K SUNOS - could be replaced by generic code */
......@@ -113,6 +115,7 @@ void GC_push_regs()
asm("movl d7,sp@"); asm("jbsr _GC_push_one");
asm("addqw #0x4,sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif
# if defined(M68K) && defined(HP)
......@@ -135,6 +138,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif /* M68K HP */
# if defined(M68K) && defined(AMIGA)
......@@ -158,6 +162,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# else /* !__GNUC__ */
GC_push_one(getreg(REG_A2));
GC_push_one(getreg(REG_A3));
......@@ -174,6 +179,7 @@ void GC_push_regs()
GC_push_one(getreg(REG_D5));
GC_push_one(getreg(REG_D6));
GC_push_one(getreg(REG_D7));
# define HAVE_PUSH_REGS
# endif /* !__GNUC__ */
# endif /* AMIGA */
......@@ -196,10 +202,12 @@ void GC_push_regs()
PushMacReg(d7);
add.w #4,sp ; fix stack.
}
# define HAVE_PUSH_REGS
# undef PushMacReg
# endif /* THINK_C */
# if defined(__MWERKS__)
PushMacRegisters();
# define HAVE_PUSH_REGS
# endif /* __MWERKS__ */
# endif /* MACOS */
......@@ -222,13 +230,15 @@ void GC_push_regs()
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 %ebx"); asm("call _GC_push_one"); asm("addl $4,%esp");
# define HAVE_PUSH_REGS
# endif
# if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \
|| ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(NETBSD) && 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 section handles FreeBSD with ELF. */
......@@ -243,6 +253,7 @@ void GC_push_regs()
asm("pushl %esi; 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");
# define HAVE_PUSH_REGS
# endif
# if ( defined(I386) && defined(BEOS) && defined(__ELF__) )
......@@ -254,6 +265,7 @@ void GC_push_regs()
asm("pushl %esi; 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");
# define HAVE_PUSH_REGS
# endif
# if defined(I386) && defined(MSWIN32) && !defined(__MINGW32__) \
......@@ -280,6 +292,7 @@ void GC_push_regs()
__asm push edi
__asm call GC_push_one
__asm add esp,4
# define HAVE_PUSH_REGS
# endif
# if defined(I386) && (defined(SVR4) || defined(SCO) || defined(SCO_ELF))
......@@ -291,6 +304,7 @@ void GC_push_regs()
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 %edi"); asm("call GC_push_one"); asm("addl $4,%esp");
# define HAVE_PUSH_REGS
# endif
# ifdef NS32K
......@@ -299,14 +313,12 @@ void GC_push_regs()
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 r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
# define HAVE_PUSH_REGS
# endif
# if defined(SPARC)
{
word GC_save_regs_in_stack();
GC_save_regs_ret_val = GC_save_regs_in_stack();
}
# define HAVE_PUSH_REGS
# endif
# ifdef RT
......@@ -322,6 +334,7 @@ void GC_push_regs()
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, r15, r0"); GC_push_one(TMP_SP);
# define HAVE_PUSH_REGS
# endif
# if defined(M68K) && defined(SYSV)
......@@ -345,6 +358,7 @@ void GC_push_regs()
asm("movl %d7,%sp@"); asm("jbsr GC_push_one");
asm("addqw #0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# else /* !__GNUC__*/
asm("subq.w &0x4,%sp"); /* allocate word on top of stack */
......@@ -362,6 +376,7 @@ void GC_push_regs()
asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one");
asm("addq.w &0x4,%sp"); /* put stack back where it was */
# define HAVE_PUSH_REGS
# endif /* !__GNUC__ */
# endif /* M68K/SYSV */
......@@ -371,21 +386,19 @@ void GC_push_regs()
extern int *__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
/* other machines... */
# if !defined(M68K) && !defined(VAX) && !defined(RT)
# if !defined(SPARC) && !defined(I386) && !defined(NS32K)
# if !defined(POWERPC) && !defined(UTS4)
# if !defined(PJ) && !(defined(MIPS) && defined(LINUX))
--> bad news <--
# endif
# endif
# endif
# if !defined(HAVE_PUSH_REGS)
--> We just generated an empty GC_push_regs, which
--> is almost certainly broken. Try defining
--> USE_GENERIC_PUSH_REGS instead.
# endif
}
#endif /* !USE_GENERIC_PUSH_REGS */
#endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
#if defined(USE_GENERIC_PUSH_REGS)
void GC_generic_push_regs(cold_gc_frame)
......@@ -427,8 +440,6 @@ ptr_t cold_gc_frame;
/* needed on IA64, since some non-windowed registers are */
/* preserved. */
{
word GC_save_regs_in_stack();
GC_save_regs_ret_val = GC_save_regs_in_stack();
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
/* __builtin_ia64_flushrs(). The latter will be done */
......@@ -445,7 +456,7 @@ ptr_t cold_gc_frame;
/* the stack. Return sp. */
# ifdef SPARC
asm(" .seg \"text\"");
# ifdef SVR4
# if defined(SVR4) || defined(NETBSD)
asm(" .globl GC_save_regs_in_stack");
asm("GC_save_regs_in_stack:");
asm(" .type GC_save_regs_in_stack,#function");
......
......@@ -182,6 +182,7 @@ register int k;
ptr_t result;
DCL_LOCK_STATE;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS();
if (SMALL_OBJ(lb)) {
DISABLE_SIGNALS();
......@@ -294,6 +295,11 @@ DCL_LOCK_STATE;
return(GENERAL_MALLOC((word)lb, NORMAL));
}
/* 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);
obj_link(op) = 0;
GC_words_allocd += lw;
......@@ -338,6 +344,7 @@ DCL_LOCK_STATE;
return((GC_PTR)REDIRECT_MALLOC(n*lb));
}
#ifndef strdup
# include <string.h>
# ifdef __STDC__
char *strdup(const char *s)
......@@ -346,11 +353,16 @@ DCL_LOCK_STATE;
char *s;
# endif
{
size_t len = strlen + 1;
size_t len = strlen(s) + 1;
char * result = ((char *)REDIRECT_MALLOC(len+1));
BCOPY(s, result, len+1);
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 */
/* Explicitly deallocate an object p. */
......@@ -373,6 +385,7 @@ DCL_LOCK_STATE;
/* Required by ANSI. It's not my fault ... */
h = HBLKPTR(p);
hhdr = HDR(h);
GC_ASSERT(GC_base(p) == p);
# if defined(REDIRECT_MALLOC) && \
(defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
|| defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
......@@ -454,7 +467,10 @@ void GC_free_inner(GC_PTR p)
}
#endif /* THREADS */
# ifdef REDIRECT_MALLOC
# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
# define REDIRECT_FREE GC_free
# endif
# ifdef REDIRECT_FREE
# ifdef __STDC__
void free(GC_PTR p)
# else
......@@ -463,7 +479,7 @@ void GC_free_inner(GC_PTR p)
# endif
{
# ifndef IGNORE_FREE
GC_free(p);
REDIRECT_FREE(p);
# endif
}
# endif /* REDIRECT_MALLOC */
......@@ -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__
GC_PTR realloc(GC_PTR p, size_t lb)
# else
......@@ -151,13 +155,9 @@ int obj_kind;
size_t lb;
# endif
{
# ifdef REDIRECT_REALLOC
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. */
......@@ -177,6 +177,7 @@ register int k;
lw = ROUNDED_UP_WORDS(lb);
n_blocks = OBJ_SZ_TO_BLOCKS(lw);
init = GC_obj_kinds[k].ok_init;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
......@@ -286,6 +287,7 @@ register struct obj_kind * kind = GC_obj_kinds + k;
register ptr_t op;
DCL_LOCK_STATE;
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
......@@ -354,6 +356,7 @@ DCL_LOCK_STATE;
return;
}
lw = ALIGNED_WORDS(lb);
if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
......@@ -375,6 +378,7 @@ DCL_LOCK_STATE;
while ((hbp = *rlh) != 0) {
hhdr = HDR(hbp);
*rlh = hhdr -> hb_next;
hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
# ifdef PARALLEL_MARK
{
signed_word my_words_allocd_tmp = GC_words_allocd_tmp;
......@@ -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
/* Allocate lb bytes of pointerfree, untraced, uncollectable data */
/* This is normally roughly equivalent to the system malloc. */
......
......@@ -275,33 +275,72 @@ void GC_clear_roots GC_PROTO((void))
}
/* Internal use only; lock held. */
void GC_remove_tmp_roots()
static void GC_remove_root_at_pos(i)
int i;
{
register int i;
for (i = 0; i < n_root_sets; ) {
if (GC_static_roots[i].r_tmp) {
GC_root_size -=
(GC_static_roots[i].r_end - GC_static_roots[i].r_start);
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--;
} else {
i++;
}
}
# if !defined(MSWIN32) && !defined(MSWINCE)
{
}
#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()
{
register int i;
for (i = 0; i < n_root_sets; ) {
if (GC_static_roots[i].r_tmp) {
GC_remove_root_at_pos(i);
} else {
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)
/* Workaround for the OS mapping and unmapping behind our back: */
......@@ -573,8 +612,11 @@ ptr_t cold_gc_frame;
/* Mark thread local free lists, even if their mark */
/* 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
GC_mark_thread_local_free_lists();
if (GC_world_stopped) GC_mark_thread_local_free_lists();
# endif
/*
......
#include <sys/regdef.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
......
.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))
return(p);
}
sz = WORDS_TO_BYTES(hhdr -> hb_sz);
if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
if (sz > MAXOBJBYTES) {
base = (ptr_t)HBLKPTR(p);
limit = base + sz;
if ((ptr_t)p >= limit) {
......@@ -165,7 +165,7 @@ void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) =
pdispl = HBLKDISPL(p);
map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
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;
}
return(p);
......
......@@ -27,10 +27,43 @@ signed_word GC_mem_found = 0;
/* nonzero. */
#endif /* PARALLEL_MARK */
static void report_leak(p, sz)
ptr_t p;
word sz;
/* We defer printing of leaked objects until we're done with the GC */
/* cycle, since the routine for printing objects needs to run outside */
/* 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 (GC_n_leaked < MAX_LEAKED) {
GC_have_errors = TRUE;
GC_leaked[GC_n_leaked++] = leaked;
/* Make sure it's not reclaimed this cycle */
GC_set_mark_bit(leaked);
}
}
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 {
......@@ -38,12 +71,17 @@ word sz;
}
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) \
{ \
report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \
HDR(hblk) -> hb_sz); \
GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
}
/*
......@@ -866,7 +904,7 @@ void GC_print_block_list()
* Clear *flp.
* This must be done before dropping a list of free gcj-style objects,
* 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)
ptr_t *flp;
......
......@@ -13,9 +13,8 @@
/*
* Support code for Solaris threads. Provides functionality we wish Sun
* 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)
# include "private/gc_priv.h"
......
......@@ -37,6 +37,10 @@
# include <unistd.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
* than this when a stop-the-world GC happens, set_max_lwps will be
......@@ -361,7 +365,7 @@ static void restart_all_lwps()
sizeof (prgregset_t)) != 0) {
int j;
for(j = 0; j < NGREG; j++)
for(j = 0; j < NPRGREG; j++)
{
GC_printf3("%i: %x -> %x\n", j,
GC_lwp_registers[i][j],
......@@ -821,7 +825,7 @@ int GC_thr_suspend(thread_t target_thread)
if (result == 0) {
t = GC_lookup_thread(target_thread);
if (t == 0) ABORT("thread unknown to GC");
t -> flags |= SUSPENDED;
t -> flags |= SUSPNDED;
}
UNLOCK();
return(result);
......@@ -837,7 +841,7 @@ int GC_thr_continue(thread_t target_thread)
if (result == 0) {
t = GC_lookup_thread(target_thread);
if (t == 0) ABORT("thread unknown to GC");
t -> flags &= ~SUSPENDED;
t -> flags &= ~SUSPNDED;
}
UNLOCK();
return(result);
......@@ -923,7 +927,7 @@ GC_thr_create(void *stack_base, size_t stack_size,
my_flags |= CLIENT_OWNS_STACK;
}
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,
arg, flags & ~THR_DETACHED, &my_new_thread);
if (result == 0) {
......
......@@ -28,7 +28,10 @@ few minutes to complete.
#include <stdio.h>
#include <stdlib.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"
#else
# include "gc_alloc.h"
......@@ -189,25 +192,32 @@ int APIENTRY WinMain(
# endif
#endif
GC_init();
# if defined(MACOS) // MacOS
char* argv_[] = {"test_cpp", "10"}; // doesn't
argv = argv_; // have a
argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
# endif
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__
int *x = (int *)gc_alloc::allocate(sizeof(int));
# else
int *x = (int *)alloc::allocate(sizeof(int));
# endif
# endif
*x = 29;
x -= 3;
# ifdef USE_STD_ALLOCATOR
*xptr = x;
x = 0;
# endif
if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
GC_printf0( "usage: test_cpp number-of-iterations\n" );
exit( 1 );}
GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
n = 10;}
for (iters = 1; iters <= n; iters++) {
GC_printf1( "Starting iteration %d\n", iters );
......@@ -268,9 +278,10 @@ int APIENTRY WinMain(
D::Test();
F::Test();}
# if !defined(__GNUC__) && !defined(MACOS)
my_assert (29 == x[3]);
# ifdef USE_STD_ALLOCATOR
x = *xptr;
# endif
my_assert (29 == x[0]);
GC_printf0( "The test appears to have succeeded.\n" );
return( 0 );}
......
......@@ -4,13 +4,14 @@
int main()
{
# 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_detach "
"-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
# endif
# 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");
# endif
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
......@@ -19,6 +20,17 @@ int main()
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
printf("-lthread -ldl\n");
# 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;
}
......@@ -437,6 +437,7 @@ void GC_init_explicit_typing()
for (; bm != 0; bm >>= 1, current_p++) {
if (bm & 1) {
current = *current_p;
FIXUP_POINTER(current);
if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) {
PUSH_CONTENTS((ptr_t)current, mark_stack_ptr,
mark_stack_limit, current_p, exit1);
......@@ -674,7 +675,7 @@ DCL_LOCK_STATE;
if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
FASTUNLOCK();
op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind);
if (0 == op) return(0);
if (0 == op) return 0;
# ifdef MERGE_SIZES
lw = GC_size_map[lb]; /* May have been uninitialized. */
# endif
......
#define GC_VERSION_MAJOR 6
#define GC_VERSION_MINOR 1
#define GC_ALPHA_VERSION 3
/* The version here should match that in configure/configure.in */
/* Eventually this one may become unnecessary. For now we need */
/* 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
#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
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 */
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