diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index fd02f6ac40dc85dde762e84e3751d580ac4b7175..ba8abd13a0781a562715d68e3399cdc65f99f7bd 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,8 @@
+2000-05-07  Bryce McKinlay  <bryce@albatross.co.nz>
+
+	Imported version 5.0alpha7.
+        * acinclude.m4: Update version to 5.0a7.
+
 2000-04-26  Jakub Jelinek  <jakub@redhat.com>
 
 	* gcconfig.h (SPARC): Define ALIGNMENT to 8 for 64bit SPARC.
diff --git a/boehm-gc/NT_MAKEFILE b/boehm-gc/NT_MAKEFILE
index 52f6f4ae3a08d4f42c9dc01408c9116476ef8952..a642262a9ca41b4b13a5dc4f91e64f3010397a0e 100644
--- a/boehm-gc/NT_MAKEFILE
+++ b/boehm-gc/NT_MAKEFILE
@@ -10,10 +10,10 @@ OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_r
 all: gctest.exe cord\de.exe test_cpp.exe
 
 .c.obj:
-	$(cc) $(cdebug) $(cflags) $(cvars) -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -D__STDC__ $*.c /Fo$*.obj
+	$(cc) $(cdebug) $(cflags) $(cvars) -DSILENT -DALL_INTERIOR_POINTERS -D__STDC__ $*.c /Fo$*.obj
 
 .cpp.obj:
-	$(cc) $(cdebug) $(cflags) $(cvars) -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS $*.CPP /Fo$*.obj
+	$(cc) $(cdebug) $(cflags) $(cvars) -DSILENT -DALL_INTERIOR_POINTERS $*.CPP /Fo$*.obj
 
 $(OBJS) test.obj: gc_priv.h gc_hdrs.h gc.h
 
diff --git a/boehm-gc/README b/boehm-gc/README
index f800ee46322be6fa0a8049dbede9185abc468db3..b89779034fb40bcd2cb45a8b6be7214d03e2fe86 100644
--- a/boehm-gc/README
+++ b/boehm-gc/README
@@ -15,7 +15,7 @@ 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.
 
-This is version 5.0alpha6 of a conservative garbage collector for C and C++.
+This is version 5.0alpha7 of a conservative garbage collector for C and C++.
 
 You might find a more recent version of this at
 
@@ -26,8 +26,8 @@ HISTORY -
   Early versions of this collector were developed as a part of research
 projects supported in part by the National Science Foundation
 and the Defense Advance Research Projects Agency.
-Much of the code was rewritten by Hans-J. Boehm (boehm@acm.org) at Xerox PARC
-and at SGI.
+Much of the code was rewritten by Hans-J. Boehm (boehm@acm.org) at Xerox PARC,
+SGI, and HP Labs.
 
 Some other contributors:  
 
@@ -1576,9 +1576,31 @@ Since 5.0 alpha4
  - Added Mingw32 support.  (Thanks again to Jeff Sturm for the patch.)
  - Changed the alpha port to use the generic register scanning code instead
    of alpha_mach_dep.s.  Alpha_mach_dep.s doesn't look for pointers in fp
-   registers, but gcc sometimes spills pointers there.  (Thanks to Manuel Serrano
-   for helping me debug this by email.)  Changed the IA64 code to do something
-   similar for similar reasons.
+   registers, but gcc sometimes spills pointers there.  (Thanks to Manuel
+   Serrano for helping me debug this by email.)  Changed the IA64 code to
+   do something similar for similar reasons.
+
+Since 5.0alpha6:
+ - -DREDIRECT_MALLOC was broken in alpha6. Fixed.
+ - Cleaned up gc_ccp.h slightly, thus also causing the HP C++ compiler to
+   accept it.
+ - Removed accidental reference to dbg_mlc.c, which caused dbg_mlc.o to be
+   linked into every executable.
+ - Added PREFETCH to bitmap marker.  Changed it to use the header cache.
+ - GC_push_marked sometimes pushed one object too many, resulting in a
+   segmentation fault in GC_mark_from_mark_stack.  This was probably an old
+   bug.  It finally showed up in gctest on win32.
+ - Gc_priv.h erroneously #defined GC_incremental to be TRUE instead of FALSE
+   when SMALL_CONFIG was defined.  This was no doubt a major performance bug for
+   the default win32 configuration.
+ - Removed -DSMALL_CONFIG from NT_MAKEFILE.  It seemed like an anchronism now
+   that the average PC has 64MB or so.
+ - Integrated Bryce McKinley's patches for linux threads and dynamic loading
+   from the libgcj tree.  Turned on dynamic loading support for Linux/PPC.
+ - Changed the stack finding code to use environ on HP/UX.  (Thanks
+   to Gustavo Rodriguez-Rivera for the suggestion.)  This should probably
+   be done on other platforms, too.  Since I can't test those, that'll
+   wait until after 5.0.
 
 To do:
  - Very large root set sizes (> 16 MB or so) could cause the collector
diff --git a/boehm-gc/acinclude.m4 b/boehm-gc/acinclude.m4
index e413c6ab9df6ceddeb5b96f1a1c477d7e7a039d0..c9e36ceeb38e84ca4dfbba6973274066bab50777 100644
--- a/boehm-gc/acinclude.m4
+++ b/boehm-gc/acinclude.m4
@@ -31,7 +31,7 @@ AC_SUBST(boehm_gc_basedir)
 
 AC_CANONICAL_HOST
 
-AM_INIT_AUTOMAKE(boehm-gc, 5.0a6, no-define)
+AM_INIT_AUTOMAKE(boehm-gc, 5.0a7, no-define)
 
 # FIXME: We temporarily define our own version of AC_PROG_CC.  This is
 # copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS.  We
diff --git a/boehm-gc/dbg_mlc.c b/boehm-gc/dbg_mlc.c
index 776dc3f6ee88bb6d4ac4e6f955515611fd3dd851..f329cc81a4c27ea92f039ef5344f0b32c7274058 100644
--- a/boehm-gc/dbg_mlc.c
+++ b/boehm-gc/dbg_mlc.c
@@ -428,7 +428,31 @@ GC_PTR p;
     GC_end_stubborn_change(q);
 }
 
-#endif /* STUBBORN_ALLOC */
+#else /* !STUBBORN_ALLOC */
+
+# ifdef __STDC__
+    GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
+# else
+    GC_PTR GC_debug_malloc_stubborn(lb, s, i)
+    size_t lb;
+    char * s;
+    int i;
+# endif
+{
+    return GC_debug_malloc(lb, OPT_RA s, i);
+}
+
+void GC_debug_change_stubborn(p)
+GC_PTR p;
+{
+}
+
+void GC_debug_end_stubborn_change(p)
+GC_PTR p;
+{
+}
+
+#endif /* !STUBBORN_ALLOC */
 
 # ifdef __STDC__
     GC_PTR GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
diff --git a/boehm-gc/finalize.c b/boehm-gc/finalize.c
index 1ab56cee82ec8874df2e208facb9f0beedd183ad..e70a9ff1e993c65f30572aa33c294b17fd0b1e77 100644
--- a/boehm-gc/finalize.c
+++ b/boehm-gc/finalize.c
@@ -619,7 +619,7 @@ void GC_finalize()
 void GC_enqueue_all_finalizers()
 {
     struct finalizable_object * curr_fo, * prev_fo, * next_fo;
-    ptr_t real_ptr, real_link;
+    ptr_t real_ptr;
     register int i;
     int fo_size;
     
diff --git a/boehm-gc/gc_cpp.h b/boehm-gc/gc_cpp.h
index 36013e135b9abe0599db5bbcd6802ace67730a0b..35686fc3527af57465875082e58438afbb0b571e 100644
--- a/boehm-gc/gc_cpp.h
+++ b/boehm-gc/gc_cpp.h
@@ -255,12 +255,12 @@ inline gc_cleanup::gc_cleanup() {
     GC_finalization_proc oldProc;
     void* oldData;
     void* base = GC_base( (void *) this );
-    if (0 == base) return;
-    GC_REGISTER_FINALIZER_IGNORE_SELF( 
-        base, cleanup, (void*) ((char*) this - (char*) base), 
+    if (0 != base)  {
+      GC_REGISTER_FINALIZER_IGNORE_SELF( 
+        base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base), 
         &oldProc, &oldData );
-    if (0 != oldProc) {
-        GC_REGISTER_FINALIZER_IGNORE_SELF( base, oldProc, oldData, 0, 0 );}}
+      if (0 != oldProc) {
+        GC_REGISTER_FINALIZER_IGNORE_SELF( base, oldProc, oldData, 0, 0 );}}}
 
 inline void* operator new( 
     size_t size, 
diff --git a/boehm-gc/gc_priv.h b/boehm-gc/gc_priv.h
index f26d485ea5741a959e4349e8d8ebc877de95b2a8..22e9728c8a66b4120d00df71c48892be077d0ed1 100644
--- a/boehm-gc/gc_priv.h
+++ b/boehm-gc/gc_priv.h
@@ -1415,7 +1415,7 @@ extern GC_bool GC_objects_are_marked;	/* There are marked objects in  */
   extern GC_bool GC_incremental;
 			/* Using incremental/generational collection. */
 #else
-# define GC_incremental TRUE
+# define GC_incremental FALSE
 			/* Hopefully allow optimizer to remove some code. */
 #endif
 
diff --git a/boehm-gc/gcconfig.h b/boehm-gc/gcconfig.h
index 49b0fb03627ad70898008a04d0cd246f26b65d7f..141bdb87dc0726e8061a590a18a2d4a78e6c43a4 100644
--- a/boehm-gc/gcconfig.h
+++ b/boehm-gc/gcconfig.h
@@ -386,6 +386,11 @@
  *		to the nearest plausible page boundary, and use that instead
  *		of STACKBOTTOM.
  *
+ * Gustavo Rodriguez-Rivera points out that on most (all?) Unix machines,
+ * the value of environ is a pointer that can serve as STACKBOTTOM.
+ * I expect that HEURISTIC2 can be replaced by this approach, which
+ * interferes far less with debugging. 
+ *
  * If no expression for STACKBOTTOM can be found, and neither of the above
  * heuristics are usable, the collector can still be used with all of the above
  * undefined, provided one of the following is done:
@@ -1023,7 +1028,11 @@
 	/* this.)							*/
 #       define STACKBOTTOM ((ptr_t) 0x7b033000)  /* from /etc/conf/h/param.h */
 #   else
-#       define HEURISTIC2
+	/* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2	*/
+	/* to this.  We'll probably do this on other platforms, too.	*/
+	/* For now I'll use it where I can test it.			*/
+	extern char ** environ;
+#       define STACKBOTTOM ((ptr_t)environ)
 #   endif
 #   define STACK_GROWS_UP
 #   define DYNAMIC_LOADING
@@ -1109,7 +1118,6 @@
 		/* Requires Linux 2.3.47 or later.	*/
 	extern int _end;
 #	define DATAEND (&_end)
-	/* PREFETCH appears to have a large performance impact.	*/
 #	define PREFETCH(x) \
 	  __asm__ ("	lfetch	[%0]": : "r"((void *)(x)))
 #	define PREFETCH_FOR_WRITE(x) \
diff --git a/boehm-gc/mark.c b/boehm-gc/mark.c
index d164702bf1ead65e4abe16f891b1e92ab7b10c3f..d77e6acd8daf9ed427adff3fec99f0a3cf2a6f89 100644
--- a/boehm-gc/mark.c
+++ b/boehm-gc/mark.c
@@ -493,7 +493,8 @@ void GC_mark_from_mark_stack()
             if ((signed_word)descr < 0) {
               current = *current_p;
 	      if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
-                PUSH_CONTENTS((ptr_t)current, GC_mark_stack_top_reg,
+		PREFETCH(current);
+                HC_PUSH_CONTENTS((ptr_t)current, GC_mark_stack_top_reg,
 			      mark_stack_limit, current_p, exit1);
 	      }
             }
@@ -1116,6 +1117,7 @@ struct hblk *h;
 register hdr * hhdr;
 {
     register int sz = hhdr -> hb_sz;
+    register int descr = hhdr -> hb_descr;
     register word * p;
     register int word_no;
     register word * lim;
@@ -1123,19 +1125,14 @@ register hdr * hhdr;
     register mse * mark_stack_limit = &(GC_mark_stack[GC_mark_stack_size]);
     
     /* Some quick shortcuts: */
-	{ 
-	    struct obj_kind *ok = &(GC_obj_kinds[hhdr -> hb_obj_kind]);
-	    if ((0 | DS_LENGTH) == ok -> ok_descriptor
-		&& FALSE == ok -> ok_relocate_descr)
-		return;
-	}
+	if ((0 | DS_LENGTH) == descr) return;
         if (GC_block_empty(hhdr)/* nothing marked */) return;
 #   ifdef GATHERSTATS
         GC_n_rescuing_pages++;
 #   endif
     GC_objects_are_marked = TRUE;
     if (sz > MAXOBJSZ) {
-        lim = (word *)(h + 1);
+        lim = (word *)h + HDR_WORDS;
     } else {
         lim = (word *)(h + 1) - sz;
     }
@@ -1158,10 +1155,6 @@ register hdr * hhdr;
       GC_mark_stack_top_reg = GC_mark_stack_top;
       for (p = (word *)h + HDR_WORDS, word_no = HDR_WORDS; p <= lim;
          p += sz, word_no += sz) {
-         /* This ignores user specified mark procs.  This currently	*/
-         /* doesn't matter, since marking from the whole object		*/
-         /* is always sufficient, and we will eventually use the user	*/
-         /* mark proc to avoid any bogus pointers.			*/
          if (mark_bit_from_hdr(hhdr, word_no)) {
            /* Mark from fields inside the object */
              PUSH_OBJ((word *)p, hhdr, GC_mark_stack_top_reg, mark_stack_limit);
diff --git a/boehm-gc/os_dep.c b/boehm-gc/os_dep.c
index 76e909f7971ee415fa4236b92a06281e37541c21..636495ed039c38536f9978d56485e5e84d8d2949 100644
--- a/boehm-gc/os_dep.c
+++ b/boehm-gc/os_dep.c
@@ -642,31 +642,48 @@ ptr_t GC_get_stack_base()
 
 #ifdef LINUX_STACKBOTTOM
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 # define STAT_SKIP 27   /* Number of fields preceding startstack	*/
 			/* field in /proc/self/stat			*/
 
   ptr_t GC_linux_stack_base(void)
   {
-    FILE *f;
+    /* We read the stack base value from /proc/self/stat.  We do this	*/
+    /* using direct I/O system calls in order to avoid calling malloc   */
+    /* in case REDIRECT_MALLOC is defined.				*/ 
+#   define STAT_BUF_SIZE 4096
+#   ifdef USE_LD_WRAP
+#	define STAT_READ __real_read
+#   else
+#	define STAT_READ read
+#   endif    
+    char stat_buf[STAT_BUF_SIZE];
+    int f;
     char c;
     word result = 0;
-    int i;
+    size_t i, buf_offset = 0;
 
-    f = fopen("/proc/self/stat", "r");
-    if (NULL == f) ABORT("Couldn't open /proc/self/stat");
-    c = getc(f);
+    f = open("/proc/self/stat", O_RDONLY);
+    if (f < 0 || read(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
+	ABORT("Couldn't read /proc/self/stat");
+    }
+    c = stat_buf[buf_offset++];
     /* Skip the required number of fields.  This number is hopefully	*/
     /* constant across all Linux implementations.			*/
       for (i = 0; i < STAT_SKIP; ++i) {
-	while (isspace(c)) c = getc(f);
-	while (!isspace(c)) c = getc(f);
+	while (isspace(c)) c = stat_buf[buf_offset++];
+	while (!isspace(c)) c = stat_buf[buf_offset++];
       }
-    while (isspace(c)) c = getc(f);
+    while (isspace(c)) c = stat_buf[buf_offset++];
     while (isdigit(c)) {
       result *= 10;
       result += c - '0';
-      c = getc(f);
+      c = stat_buf[buf_offset++];
     }
+    close(f);
     if (result < 0x10000000) ABORT("Absurd stack bottom value");
     return (ptr_t)result;
   }
diff --git a/boehm-gc/reclaim.c b/boehm-gc/reclaim.c
index 1847e590aad0e4ebeb9faa5efacb136e5fbf186f..57c652ef2655cfa4ebeb5f262dc38614ad8bb905 100644
--- a/boehm-gc/reclaim.c
+++ b/boehm-gc/reclaim.c
@@ -29,13 +29,8 @@ word sz;
     } else {
         GC_err_printf0("Leaked composite object at ");
     }
-    if (GC_debugging_started && GC_has_debug_info(p)) {
-        GC_print_obj(p);
-    } else {
-        GC_err_printf2("0x%lx (appr. size = %ld)\n",
-       		      (unsigned long)p,
-       		      (unsigned long)WORDS_TO_BYTES(sz));
-    }
+    GC_print_heap_obj(p);
+    GC_err_printf0("\n");
 }
 
 #   define FOUND_FREE(hblk, word_no) \
diff --git a/boehm-gc/version.h b/boehm-gc/version.h
index c7095488bd53e7c3ee35665014e9a92b41d686fe..2aedacce5319df1d232815168b17bd7a72408d40 100644
--- a/boehm-gc/version.h
+++ b/boehm-gc/version.h
@@ -1,6 +1,6 @@
 #define GC_VERSION_MAJOR 5
 #define GC_VERSION_MINOR 0
-#define GC_ALPHA_VERSION 6
+#define GC_ALPHA_VERSION 7
 
 #   define GC_NOT_ALPHA 0xff