Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 gcl (2.6.7+dfsga-21) unstable; urgency=high
 .
   * near out of memory robustification
Author: Camm Maguire <camm@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- gcl-2.6.7+dfsga.orig/configure
+++ gcl-2.6.7+dfsga/configure
@@ -4813,8 +4813,8 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_sysconf" >&5
 $as_echo "$ac_cv_lib_c_sysconf" >&6; }
 if test "x$ac_cv_lib_c_sysconf" = xyes; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking \"for _SC_CLK_TCK\"" >&5
-$as_echo_n "checking \"for _SC_CLK_TCK\"... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking _SC_CLK_TCK" >&5
+$as_echo_n "checking _SC_CLK_TCK... " >&6; }
 		if test "$cross_compiling" = yes; then :
   hz=0
 else
@@ -4847,6 +4847,42 @@ fi
 
 	        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hz" >&5
 $as_echo "$hz" >&6; }
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking _SC_PHYS_PAGES" >&5
+$as_echo_n "checking _SC_PHYS_PAGES... " >&6; }
+		if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+			#include <stdio.h>
+			#include <unistd.h>
+			int main() {
+			   FILE *fp=fopen("conftest1","w");
+			   fprintf(fp,"%lu\n",sysconf(_SC_PHYS_PAGES));
+			   fclose(fp);
+			   return 0;
+			}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  phys=`cat conftest1`
+			 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $phys" >&5
+$as_echo "$phys" >&6; }
+
+$as_echo "#define HAVE_SYSCONF_PHYS_PAGES \$phys" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
 fi
 
 fi
@@ -6132,6 +6168,55 @@ fi
 
 
 
+# pagewidth
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pagewidth" >&5
+$as_echo_n "checking for pagewidth... " >&6; }
+if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+	    #include <stdio.h>
+            #include <unistd.h>
+
+int
+main ()
+{
+
+	    size_t i=getpagesize(),j;
+	    FILE *fp=fopen("conftest1","w");
+	    for (j=0;i>>=1;j++);
+	    if (j<12) {printf("pagewidth %u is too small\n",j);return -1;}
+	    fprintf(fp,"%u",j);
+	    return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  PAGEWIDTH=`cat conftest1`
+else
+  PAGEWIDTH=0
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PAGEWIDTH" >&5
+$as_echo "$PAGEWIDTH" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define PAGEWIDTH $PAGEWIDTH
+_ACEOF
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required object alignment" >&5
 $as_echo_n "checking for required object alignment... " >&6; }
 if test "$cross_compiling" = yes; then :
@@ -6291,56 +6376,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
-# pagewidth
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pagewidth" >&5
-$as_echo_n "checking for pagewidth... " >&6; }
-if test "$cross_compiling" = yes; then :
-  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run test program while cross compiling
-See \`config.log' for more details" "$LINENO" 5; }
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-	    #include <stdio.h>
-            #include <unistd.h>
-
-int
-main ()
-{
-
-	    size_t i=getpagesize(),j;
-	    FILE *fp=fopen("conftest1","w");
-	    for (j=0;i>>=1;j++);
-	    if (j<12) {printf("pagewidth %u is too small\n",j);return -1;}
-	    fprintf(fp,"%u",j);
-	    return 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  PAGEWIDTH=`cat conftest1`
-else
-  PAGEWIDTH=0
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PAGEWIDTH" >&5
-$as_echo "$PAGEWIDTH" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define PAGEWIDTH $PAGEWIDTH
-_ACEOF
-
-
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sbrk" >&5
 $as_echo_n "checking for sbrk... " >&6; }
 HAVE_SBRK=""
--- gcl-2.6.7+dfsga.orig/configure.in
+++ gcl-2.6.7+dfsga/configure.in
@@ -694,7 +694,7 @@ esac
 
 AC_CHECK_HEADER(unistd.h,
 	AC_CHECK_LIB(c,sysconf,
-		AC_MSG_CHECKING("for _SC_CLK_TCK")
+		AC_MSG_CHECKING(_SC_CLK_TCK)
 		AC_TRY_RUN([#include <unistd.h>
 		            #include <stdio.h>
 		            int
@@ -707,7 +707,22 @@ AC_CHECK_HEADER(unistd.h,
 			    hz=`cat conftest1`
 			    AC_DEFINE_UNQUOTED(HZ,$hz,[time system constant])
 			    ,hz=0,hz=0)
-	        [AC_MSG_RESULT($hz)]))
+	        [AC_MSG_RESULT($hz)]
+		AC_MSG_CHECKING(_SC_PHYS_PAGES)
+		AC_RUN_IFELSE([
+			AC_LANG_SOURCE([[
+			#include <stdio.h>
+			#include <unistd.h>
+			int main() {
+			   FILE *fp=fopen("conftest1","w");
+			   fprintf(fp,"%lu\n",sysconf(_SC_PHYS_PAGES));
+			   fclose(fp);
+			   return 0;
+			}]])],
+			[phys=`cat conftest1`
+			 AC_MSG_RESULT($phys)
+			 AC_DEFINE(HAVE_SYSCONF_PHYS_PAGES,$phys,[probe runtime phys pages for gc performance])],
+			 [AC_MSG_RESULT(no)])))
 
 
 #MY_SUBDIRS=
@@ -1132,6 +1147,26 @@ AC_RUN_IFELSE([
 	AC_DEFINE(DOUBLE_BIGENDIAN,1,[big endian word order])])
 AC_SUBST(DOUBLE_BIGENDIAN)
 
+# pagewidth
+AC_MSG_CHECKING(for pagewidth)
+AC_RUN_IFELSE([
+	AC_LANG_PROGRAM([[
+	    #include <stdio.h>
+            #include <unistd.h>
+	    ]],[[
+	    size_t i=getpagesize(),j; 
+	    FILE *fp=fopen("conftest1","w");
+	    for (j=0;i>>=1;j++);
+	    if (j<12) {printf("pagewidth %u is too small\n",j);return -1;}
+	    fprintf(fp,"%u",j);
+	    return 0;
+	]])],
+	[PAGEWIDTH=`cat conftest1`],
+	[PAGEWIDTH=0])
+AC_MSG_RESULT($PAGEWIDTH)
+AC_DEFINE_UNQUOTED(PAGEWIDTH,$PAGEWIDTH,[system pagewidth])
+AC_SUBST(PAGEWIDTH)
+
 AC_MSG_CHECKING([for required object alignment])
 AC_RUN_IFELSE([AC_LANG_PROGRAM([[
         #include <stdio.h>
@@ -1199,27 +1234,6 @@ fi
 AC_MSG_RESULT($sizeof_contblock)
 AC_DEFINE_UNQUOTED(SIZEOF_CONTBLOCK,$sizeof_contblock,[sizeof linked list for contiguous pages])
 
-
-# pagewidth
-AC_MSG_CHECKING(for pagewidth)
-AC_RUN_IFELSE([
-	AC_LANG_PROGRAM([[
-	    #include <stdio.h>
-            #include <unistd.h>
-	    ]],[[
-	    size_t i=getpagesize(),j; 
-	    FILE *fp=fopen("conftest1","w");
-	    for (j=0;i>>=1;j++);
-	    if (j<12) {printf("pagewidth %u is too small\n",j);return -1;}
-	    fprintf(fp,"%u",j);
-	    return 0;
-	]])],
-	[PAGEWIDTH=`cat conftest1`],
-	[PAGEWIDTH=0])
-AC_MSG_RESULT($PAGEWIDTH)
-AC_DEFINE_UNQUOTED(PAGEWIDTH,$PAGEWIDTH,[system pagewidth])
-AC_SUBST(PAGEWIDTH)
-
 AC_MSG_CHECKING([for sbrk])
 HAVE_SBRK=""
 AC_TRY_RUN([#include <unistd.h>
--- gcl-2.6.7+dfsga.orig/h/protoize.h
+++ gcl-2.6.7+dfsga/h/protoize.h
@@ -1840,3 +1840,7 @@ struct htent *gethash(object,object);
 
 int
 update_real_maxpage(void);
+
+void
+set_tm_maxpage(struct typemanager *,fixnum);
+
--- gcl-2.6.7+dfsga.orig/h/object.h
+++ gcl-2.6.7+dfsga/h/object.h
@@ -343,13 +343,6 @@ struct package {
 EXTER struct package *pack_pointer;	/*  package pointer  */
 
 #define Scdr(a_) ({union lispunion _t={.vw=(a_)->c.c_cdr};unmark(&_t);_t.vw;})
-/* #define pageinfo(x) ((struct pageinfo *)(((ufixnum)x)&(-PAGESIZE))) */
-/* #define make_cons(a_,b_) ({struct typemanager *tm=tm_table+t_cons;\ */
-/*                            object _x=tm->tm_free;\ */
-/* 			   _x==OBJNULL ? make_cons1(a_,b_) : \ */
-/* 			     ({tm->tm_free=OBJ_LINK(_x);\ */
-/* 			       tm->tm_nfree--;\ */
-/* 			       _x->c.c_car=a_;_x->c.c_cdr=b_;pageinfo(_x)->in_use++;_x;});}) */
 
 struct cons {
   /* FIRSTWORD; */
@@ -938,8 +931,10 @@ long holepage;			/*  hole pages  */
 /* int nrbpage;			  number of relblock pages  */
   
 
-EXTER 
-char *rb_start;			/*  relblock start  */
+#ifdef SGC
+EXTER char *old_rb_start;			/*  read-only relblock start  */
+#endif
+EXTER char *rb_start;			/*  relblock start  */
 EXTER char *rb_end;			/*  relblock end  */
 EXTER char *rb_limit;			/*  relblock limit  */
 EXTER char *rb_pointer;		/*  relblock pointer  */
--- gcl-2.6.7+dfsga.orig/h/unrandomize.h
+++ gcl-2.6.7+dfsga/h/unrandomize.h
@@ -17,9 +17,9 @@
     if (sizeof(long)==4) flag|=ADDR_LIMIT_3GB|ADDR_COMPAT_LAYOUT;
 
     if (pers==-1) {printf("personality failure %d\n",errno);exit(-1);}
-    if (!(pers & flag) && !getenv("GCL_UNRANDOMIZE")) {
+    if ((pers & flag)!=flag && !getenv("GCL_UNRANDOMIZE")) {
       errno=0;
-      if (personality(pers | flag) != -1 && personality(0xffffffffUL) & flag) {
+      if (personality(pers | flag) != -1 && (personality(0xffffffffUL) & flag)==flag) {
 	int i;
 	char **n,**a;
 	for (i=0;envp[i];i++);
--- gcl-2.6.7+dfsga.orig/h/bits.h
+++ gcl-2.6.7+dfsga/h/bits.h
@@ -4,12 +4,20 @@
 #include "arth.h"
 
 #define LM(a_) AM(AT(SIZEOF_LONG,8),a_)
+#if SIZEOF_LONG == 4
+#define LL 2
+#elif SIZEOF_LONG == 8
+#define LL 3
+#else
+#error "unknown SIZEOF_LONG"
+#endif 
+#define POW AM(PAGEWIDTH,AP(LL,1))
 
 struct pageinfo {
   unsigned long type:6;
-  unsigned long in_use:16;
-  unsigned long sgc_flags:3;
-  unsigned long magic:LM(25);
+  unsigned long magic:7;
+  unsigned long sgc_flags:2;
+  unsigned long in_use:LM(15);
   struct pageinfo *next;
 };
   
--- gcl-2.6.7+dfsga.orig/h/gclincl.h.in
+++ gcl-2.6.7+dfsga/h/gclincl.h.in
@@ -171,6 +171,9 @@
 /* have sv_onstack */
 #undef HAVE_SV_ONSTACK
 
+/* probe runtime phys pages for gc performance */
+#undef HAVE_SYSCONF_PHYS_PAGES
+
 /* Define to 1 if you have the <sys/ioctl.h> header file. */
 #undef HAVE_SYS_IOCTL_H
 
--- gcl-2.6.7+dfsga.orig/h/page.h
+++ gcl-2.6.7+dfsga/h/page.h
@@ -25,15 +25,15 @@
 #define ROUND_UP_PTR(n)	(((long)(n) + (PTR_ALIGN-1)) & ~(PTR_ALIGN-1))
 #define ROUND_DOWN_PTR(n) (((long)(n)  & ~(PTR_ALIGN-1)))
 
-/* alignment required for contiguous pointers */
+/* minimum size required for contiguous pointers */
 #if PTR_ALIGN < SIZEOF_CONTBLOCK
-#define CPTR_ALIGN SIZEOF_CONTBLOCK
+#define CPTR_SIZE SIZEOF_CONTBLOCK
 #else
-#define CPTR_ALIGN PTR_ALIGN
+#define CPTR_SIZE PTR_ALIGN
 #endif
 
-#define ROUND_UP_PTR_CONT(n)	(((long)(n) + (CPTR_ALIGN-1)) & ~(CPTR_ALIGN-1))
-#define ROUND_DOWN_PTR_CONT(n) (((long)(n)  & ~(CPTR_ALIGN-1)))
+#define ROUND_UP_PTR_CONT(n)	(((long)(n) + (CPTR_SIZE-1)) & ~(CPTR_SIZE-1))
+#define ROUND_DOWN_PTR_CONT(n) (((long)(n)  & ~(CPTR_SIZE-1)))
 
 
 #ifdef SGC
@@ -99,7 +99,8 @@ extern int sgc_enabled;
 
 extern long resv_pages;
 extern int reserve_pages_for_signal_handler;
-#define	available_pages	((fixnum)(real_maxpage-page(heap_end)-2*nrbpage-resv_pages))
+/* #define CONT_MARK_PAGE (((page(heap_end)-first_data_page)*(PAGESIZE/(CPTR_SIZE*CHAR_SIZE))+PAGESIZE-1)/PAGESIZE) */
+/* #define	available_pages	((fixnum)(real_maxpage-page(heap_end)-2*nrbpage-CONT_MARK_PAGE-resv_pages)) */
 
 extern struct pageinfo *cell_list_head,*cell_list_tail,*contblock_list_head,*contblock_list_tail;
 
@@ -113,11 +114,20 @@ extern fixnum writable_pages;
 #define IS_WRITABLE(i) is_writable(i)
 
 
-EXTER long first_data_page,real_maxpage;
-EXTER void * data_start;
+EXTER long first_data_page,real_maxpage,phys_pages,available_pages;
+EXTER void *data_start;
 
 #if !defined(IN_MAIN) && defined(SGC)
 #include "writable.h"
 #endif
 
+#ifdef SGC
+#define REAL_RB_START (sgc_enabled ? old_rb_start : rb_start)
+#else
+#define REAL_RB_START rb_start
+#endif
 
+#define npage(m_) (((m_)+PAGESIZE-1)/PAGESIZE)
+#define cpage(m_) ((1+sizeof(struct pageinfo)+((CPTR_SIZE*CHAR_SIZE*(m_))/(CPTR_SIZE*CHAR_SIZE-1))+PAGESIZE-1)/PAGESIZE)
+#define mbytes(p_) (((p_)*PAGESIZE-sizeof(struct pageinfo)+(CPTR_SIZE*CHAR_SIZE)-1)/(CPTR_SIZE*CHAR_SIZE))
+#define tpage(tm_,m_) (tm_->tm_type==t_contiguous ? cpage(m_) : npage(m_))
--- gcl-2.6.7+dfsga.orig/o/alloc.c
+++ gcl-2.6.7+dfsga/o/alloc.c
@@ -80,23 +80,24 @@ add_page_to_contblock_list(void *p,fixnu
   bzero(pp,sizeof(*pp));
   pp->type=t_contiguous;
   pp->in_use=m;
+  massert(pp->in_use==m);
   pp->magic=PAGE_MAGIC;
   
-  if (contblock_list_head==NULL) contblock_list_head=p;
-  else contblock_list_tail->next=p;
-  contblock_list_tail=p;
+  if (contblock_list_head==NULL)
+    contblock_list_tail=contblock_list_head=p;
+  else if (pp > contblock_list_tail) {
+    contblock_list_tail->next=p;
+    contblock_list_tail=p;
+  }
   
 #ifdef SGC
-  if (sgc_enabled) {
-    /* fixnum i;	    */
-    /* for (i=0;i<m;i++) */
-    /*   massert(IS_WRITABLE(page(p)+i)); */
+  if (sgc_enabled)
     pp->sgc_flags=SGC_PAGE_FLAG;
-  }
 #endif
   
   ncbpage+=m;
-  insert_contblock(p+sizeof(struct pageinfo),PAGESIZE*m-sizeof(struct pageinfo));
+  p+=mbytes(m)+sizeof(struct pageinfo);
+  insert_contblock(p,PAGESIZE*m-(p-(void *)pp));
 
 }
 
@@ -110,7 +111,7 @@ inline void
 maybe_reallocate_page(struct typemanager *ntm,ufixnum count) {
 
   void **y,**n;
-  fixnum *pp,*pp1,*pp2,*ppe,yp;
+  fixnum *pp,*pp1,*ppe,yp;
   struct typemanager *tm;
   fixnum i,j,e[t_end];
   struct pageinfo *v;
@@ -155,30 +156,16 @@ maybe_reallocate_page(struct typemanager
     massert(!j);
   }
 
-  if (ntm->tm_type<t_end)
-
-    for (pp=pp1;pp<ppe;pp++)
-      add_page_to_freelist(pagetochar(*pp),ntm);
-
-  else {
-
-    massert(ntm->tm_type==t_contiguous);
-
-    for (pp=pp1;pp<ppe;pp=pp2) {
-
-      for (pp2=pp+1;pp2<ppe && *pp2==pp2[-1]+1;pp2++);
-
-      add_page_to_contblock_list(pagetoinfo(*pp),pp2-pp);
-
-    }
-      
+  for (pp=pp1;pp<ppe;pp++) {
+    struct pageinfo *pn=pagetoinfo(*pp)->next;
+    add_page_to_freelist(pagetochar(*pp),ntm);
+    pagetoinfo(*pp)->next=pn;
   }
-    
+      
 }
 
 
 int reserve_pages_for_signal_handler=30;
-int hole_overrun=0;
 
 /* If  (n >= 0 ) return pointer to n pages starting at heap end,
    These must come from the hole, so if that is exhausted you have
@@ -203,9 +190,6 @@ alloc_page(long n) {
 		       available_pages-n<=reserve_pages_for_signal_handler ? 0 : 
 		       reserve_pages_for_signal_handler))) {
 
-#ifdef SGC
-      if (in_sgc) sgc_quit();
-#endif
 
       if (in_signal_handler) {
 	fprintf(stderr,"Cant do relocatable gc in signal handler. \
@@ -223,6 +207,10 @@ eg to add 20 more do (si::set-hole-size
       
       holepage = d + n;
 
+#ifdef SGC
+      if (in_sgc) sgc_quit();
+#endif
+
       GBC(t_relocatable);
       tm_table[t_relocatable].tm_adjgbccnt--;/* hole overrun is not a call for more relocatable */
 
@@ -232,9 +220,7 @@ eg to add 20 more do (si::set-hole-size
 	 and may move heap end, so start over
       */
       if (in_sgc) {
-	hole_overrun=1;
 	sgc_start();
-	hole_overrun=0;
 	return alloc_page(n);
       }
 #endif
@@ -264,13 +250,6 @@ eg to add 20 more do (si::set-hole-size
 
   IF_ALLOCATE_ERR error("Can't allocate.  Good-bye!");
 
-/* #ifdef SGC */
-/*   if (sgc_enabled) { */
-/*     fixnum y; */
-/*     for (y=page(rb_start);y<page(core_end);y++) */
-/*       massert(IS_WRITABLE(y)); */
-/*   } */
-/* #endif */
   core_end+=PAGESIZE*(n-m);
 
   return(e);
@@ -283,6 +262,15 @@ eg to add 20 more do (si::set-hole-size
 
 struct pageinfo *cell_list_head=NULL,*cell_list_tail=NULL;;
 
+inline void
+set_tm_maxpage(struct typemanager *tm,fixnum n) {
+  
+  fixnum r=tm->tm_type==t_relocatable,j=r ? tm->tm_npage : tm->tm_maxpage;;
+  available_pages-=(n-j)*(r ? 2 : 1);
+  tm->tm_adjgbccnt*=((double)j)/n;
+  if (r) tm->tm_npage=n; else tm->tm_maxpage=n;
+}
+  
 
 inline void
 add_page_to_freelist(char *p, struct typemanager *tm) {
@@ -293,10 +281,6 @@ add_page_to_freelist(char *p, struct typ
   struct pageinfo *pp;
 
  t=tm->tm_type;
-/* #ifdef SGC */
-/*  if (sgc_enabled)  */
-/*    massert(IS_WRITABLE(page(p))); */
-/* #endif */
 
  size=tm->tm_size;
  f=tm->tm_free;
@@ -306,10 +290,11 @@ add_page_to_freelist(char *p, struct typ
  pp->magic=PAGE_MAGIC;
 
  if (cell_list_head==NULL) 
-   cell_list_head=pp;
- else
+   cell_list_tail=cell_list_head=pp;
+ else if (pp > cell_list_tail) {
    cell_list_tail->next=pp;
- cell_list_tail=pp;
+   cell_list_tail=pp;
+ }
 
  x= (object)pagetochar(page(p));
  set_type_of(x,t);
@@ -343,7 +328,7 @@ add_page_to_freelist(char *p, struct typ
  tm->tm_free=f;
  tm->tm_nfree += tm->tm_nppage;
  tm->tm_npage++;
- tm->tm_maxpage=MAX(tm->tm_npage,tm->tm_maxpage);
+ set_tm_maxpage(tm,MAX(tm->tm_npage,tm->tm_maxpage));
 
 }
 
@@ -361,10 +346,6 @@ call_after_gbc_hook(t) {
   }
 }
 
-/* #define PERCENT_FREE(tm)  ((tm->tm_percent_free ? tm->tm_percent_free : 10)/100.0) */
-/* #define PERCENT_FREE(tm)  ((tm->tm_percent_free ? tm->tm_percent_free : 30)/100.0) */
-#define PERCENT_FREE(tm)  (tm->tm_percent_free/100.0)
-
 static fixnum
 grow_linear(fixnum old, fixnum fract, fixnum grow_min, fixnum grow_max,fixnum max_delt) {
   
@@ -426,6 +407,14 @@ opt_maxpage(struct typemanager *my_tm) {
   struct typemanager *tm,*tme;
   long mro=0,tro=0;
 
+#ifdef HAVE_SYSCONF_PHYS_PAGES
+  if (page(heap_end)-first_data_page+nrbpage>=phys_pages)
+    return 0;
+#endif
+
+  if (page(core_end)>0.8*real_maxpage)
+    return 0;
+
   for (tm=tm_table,tme=tm+sizeof(tm_table)/sizeof(*tm_table);tm<tme;tm++) {
     x+=tm->tm_adjgbccnt;
     y+=MMAX_PG(tm);
@@ -455,10 +444,7 @@ opt_maxpage(struct typemanager *my_tm) {
 	   my_tm->tm_type,mmax_page,mro,(long)z,(long)y,tro,(my_tm->tm_adjgbccnt-1)/(1+x-0.9*my_tm->tm_adjgbccnt),r);
   if (r<=0.95) {
     my_tm->tm_adjgbccnt*=mmax_page/z;
-    if (my_tm->tm_type==t_relocatable)
-      my_tm->tm_npage=z+mro;
-    else
-      my_tm->tm_maxpage=z+mro;
+    set_tm_maxpage(my_tm,z+mro);
     return 1;
   }
   return 0;
@@ -530,30 +516,27 @@ alloc_from_freelist(struct typemanager *
 
 }
 
-#define npage(m_) ((m_+PAGESIZE-1)/PAGESIZE)
-
 static inline void
 grow_linear1(struct typemanager *tm) {
   
-  fixnum maxgro=available_pages,j=tm->tm_maxpage;
+  fixnum maxgro=available_pages/100;
 
   if (tm->tm_type==t_relocatable) maxgro>>=1;
 
-  tm->tm_maxpage=grow_linear(tm->tm_npage,tm->tm_growth_percent,tm->tm_min_grow, tm->tm_max_grow,maxgro);
-  tm->tm_adjgbccnt*=(double)j/tm->tm_maxpage;
+  set_tm_maxpage(tm,grow_linear(tm->tm_npage,tm->tm_growth_percent,tm->tm_min_grow, tm->tm_max_grow,maxgro));
 
 }
 
 static inline int
 too_full_p(struct typemanager *tm) {
 
-  fixnum j,k;
+  fixnum j,k,pf=tm->tm_percent_free ? tm->tm_percent_free : 30;
   struct contblock *cbp;
   struct pageinfo *pi;
 
   switch (tm->tm_type) {
   case t_relocatable:
-    return 100*(rb_limit-rb_pointer)<tm->tm_percent_free*(rb_limit-rb_start);
+    return 100*(rb_limit-rb_pointer)<pf*(rb_limit-rb_start);
     break;
   case t_contiguous:
     for (cbp=cb_pointer,k=0;cbp;cbp=cbp->cb_link) k+=cbp->cb_size;
@@ -562,10 +545,10 @@ too_full_p(struct typemanager *tm) {
       if (!sgc_enabled || pi->sgc_flags&SGC_PAGE_FLAG)
 #endif
 	j+=pi->in_use;
-    return 100*k<tm->tm_percent_free*j*PAGESIZE;
+    return 100*k<pf*j*PAGESIZE;
     break;
   default:
-    return 100*tm->tm_nfree<tm->tm_percent_free*TOTAL_THIS_TYPE(tm);
+    return 100*tm->tm_nfree<pf*TOTAL_THIS_TYPE(tm);
     break;
   }
 
@@ -574,7 +557,7 @@ too_full_p(struct typemanager *tm) {
 inline void *
 alloc_after_gc(struct typemanager *tm,fixnum n) {
 
-  if (tm->tm_npage+npage(n)>=tm->tm_maxpage) {
+  if (tm->tm_npage+tpage(tm,n)>=tm->tm_maxpage) {
 
     switch (jmp_gmp) {
     case 0: /* not in gmp call*/
@@ -608,32 +591,18 @@ struct pageinfo *contblock_list_head=NUL
 inline void
 add_pages(struct typemanager *tm,fixnum n) {
 
-  void *p;
-  fixnum m=npage(n),i;
+  fixnum m=tpage(tm,n);
 
   switch (tm->tm_type) {
   case t_contiguous:
 
-    n+=sizeof(struct pageinfo);
-    m=npage(n);
-    p = alloc_page(m);
-
-    add_page_to_contblock_list(p,m);
+    add_page_to_contblock_list(alloc_page(m),m);
 
     break;
 
   case t_relocatable:
 
-    i=nrbpage;
-#ifdef SGC
-    {
-      extern char *old_rb_start;
-      nrbpage=m+2*npage(RB_GETA+(rb_pointer-(sgc_enabled ? old_rb_start : rb_start)));
-    }
-#else
-      nrbpage=m+2*npage(RB_GETA+(rb_pointer-rb_start));	
-#endif
-    tm->tm_adjgbccnt*=(double)i/nrbpage;
+    set_tm_maxpage(tm_table+t_relocatable,m+2*tpage(tm,RB_GETA+(rb_pointer-REAL_RB_START)));
 
     rb_end=heap_end+(holepage+nrbpage)*PAGESIZE;
     rb_limit=rb_end-2*RB_GETA;
@@ -655,9 +624,9 @@ add_pages(struct typemanager *tm,fixnum
 inline void *
 alloc_after_adding_pages(struct typemanager *tm,fixnum n) {
   
-  fixnum m=npage(n);
+  fixnum m=tpage(tm,n);
 
-  if ((tm->tm_type==t_relocatable ? 2*(m-npage(rb_limit-rb_pointer)) : m) > available_pages)
+  if ((tm->tm_type==t_relocatable ? 2*(m-tpage(tm,rb_limit-rb_pointer)) : m) > available_pages)
     return NULL;
 
   if (tm->tm_npage+m>tm->tm_maxpage) {
@@ -665,7 +634,7 @@ alloc_after_adding_pages(struct typemana
     if (!IGNORE_MAX_PAGES) return NULL;
 
     grow_linear1(tm);
-    if (tm->tm_npage+m>tm->tm_maxpage) tm->tm_maxpage=tm->tm_npage+m;
+    if (tm->tm_npage+m>tm->tm_maxpage) set_tm_maxpage(tm,tm->tm_npage+m);
 
   }
 
@@ -678,27 +647,15 @@ alloc_after_adding_pages(struct typemana
 inline void *
 alloc_after_reclaiming_pages(struct typemanager *tm,fixnum n) {
 
-  fixnum m=npage(n),reloc_min,i;
+  fixnum m=tpage(tm,n),reloc_min;
 
-  if (tm->tm_type>=t_relocatable) return NULL;
+  if (tm->tm_type>=t_end) return NULL;
 
-  /* GBC(t_relocatable); */
-  /* tm_table[t_relocatable].tm_adjgbccnt--; */
-#ifdef SGC
-  {
-    extern char *old_rb_start;
-
-    reloc_min=2*npage(rb_pointer-(sgc_enabled ? old_rb_start : rb_start));
-  }
-#else
-  reloc_min=2*npage(rb_pointer-rb_start);
-#endif
+  reloc_min=2*tpage(tm,rb_pointer-REAL_RB_START);
 
   if (m<nrbpage-reloc_min) {
 
-    i=nrbpage;
-    nrbpage=reloc_min;
-    tm->tm_adjgbccnt*=(double)i/nrbpage;
+    set_tm_maxpage(tm_table+t_relocatable,reloc_min);
 
     GBC(t_relocatable);
     tm_table[t_relocatable].tm_adjgbccnt--;
@@ -713,6 +670,17 @@ alloc_after_reclaiming_pages(struct type
 
 }
 
+inline void *alloc_mem(struct typemanager *,fixnum);
+
+inline void *
+alloc_after_turning_off_sgc(struct typemanager *tm,fixnum n) {
+
+  if (!sgc_enabled) return NULL;
+  sgc_quit();
+  return alloc_mem(tm,n);
+
+}
+
 inline void *
 alloc_mem(struct typemanager *tm,fixnum n) {
 
@@ -726,6 +694,8 @@ alloc_mem(struct typemanager *tm,fixnum
     return p;
   if ((p=alloc_after_adding_pages(tm,n)))
     return p;
+  if ((p=alloc_after_turning_off_sgc(tm,n)))
+    return p;
   if ((p=alloc_after_reclaiming_pages(tm,n)))
     return p;
   return exhausted_report(tm->tm_type,tm);
@@ -955,7 +925,7 @@ init_tm(enum type t, char *name, int els
 	j = i;
   if (j >= 0) {
     tm_table[(int)t].tm_type = (enum type)j;
-    tm_table[j].tm_maxpage += maxpage;
+    set_tm_maxpage(tm_table+j,tm_table[j].tm_maxpage+maxpage);
 #ifdef SGC		
     tm_table[j].tm_sgc += sgc;
 #endif
@@ -968,16 +938,12 @@ init_tm(enum type t, char *name, int els
   tm_table[(int)t].tm_nfree = 0;
   /* tm_table[(int)t].tm_nused = 0; */
   /*tm_table[(int)t].tm_npage = 0; */  /* dont zero nrbpage.. */
-  tm_table[(int)t].tm_maxpage = maxpage;
+  set_tm_maxpage(tm_table+t,maxpage);
   tm_table[(int)t].tm_gbccount = 0;
   tm_table[(int)t].tm_adjgbccnt = 0;
   tm_table[(int)t].tm_opt_maxpage = 0;
   tm_table[(int)t].tm_distinct=distinct;
 
-  if (1) {/*FIXME(t<t_end)*/
-    tm_table[(int)t].tm_percent_free=30;
-    tm_table[(int)t].tm_growth_percent=50;
-  }
 #ifdef SGC	
   tm_table[(int)t].tm_sgc = sgc;
   tm_table[(int)t].tm_sgc_max = 3000;
@@ -1077,10 +1043,8 @@ gcl_init_alloc(void) {
      holepage=textpage;
 #endif
 
-  /* new_holepage = HOLEPAGE; */
   new_holepage = available_pages/10;
-  /* nrbpage = INIT_NRBPAGE; */
-  nrbpage = available_pages/20;
+  set_tm_maxpage(tm_table+t_relocatable,available_pages/20);
   
 #ifdef __linux__
   /* Some versions of the Linux startup code are broken.
@@ -1153,10 +1117,10 @@ gcl_init_alloc(void) {
   
   ncb = 0;
   ncbpage = 0;
-  maxcbpage = 512;
+  set_tm_maxpage(tm_table+t_contiguous,512);
 #ifdef GCL_GPROF
   if (maxcbpage<textpage)
-     maxcbpage=textpage;
+    set_tm_maxpage(tm_table+t_contiguous,textpage);
 #endif
 
 #ifndef DONT_NEED_MALLOC	
@@ -1243,8 +1207,8 @@ DEFUN_NEW("ALLOCATE-GROWTH",object,fSall
     goto END;
  tm->tm_max_grow=max;
  tm->tm_min_grow=min;
- tm->tm_growth_percent= percent;
- tm->tm_percent_free= percent_free;
+ tm->tm_growth_percent=percent;
+ tm->tm_percent_free=percent_free;
  END:
  RETURN1(res);
 }
@@ -1275,7 +1239,7 @@ DEFUN_NEW("ALLOCATE-CONTIGUOUS-PAGES",ob
 /*     printf("Allocate contiguous %ld: %d already there pages",npages,ncbpage); */
     npages=ncbpage;
   }
-  maxcbpage = npages;
+  set_tm_maxpage(tm_table+t_contiguous,npages);
   if (really_do == Cnil) 
     RETURN1(Ct);
   m = maxcbpage - ncbpage;
@@ -1323,12 +1287,12 @@ DEFUN_NEW("ALLOCATE-RELOCATABLE-PAGES",o
   CHECK_ARG_RANGE(1,2);
   if (npages  <= 0)
     FEerror("Requires positive arg",0);
-  if ((nrbpage > npages && rb_pointer >= rb_start + PAGESIZE*npages - 2*RB_GETA)
+  if ((nrbpage > npages && rb_pointer >= rb_start + PAGESIZE*npages - 2*RB_GETA)/*FIXME*/
       || 2*npages > real_maxpage-page(heap_end)-new_holepage-real_maxpage/32)
     FEerror("Can't set the limit for relocatable blocks to ~D.",
 	    1, make_fixnum(npages));
   rb_end += (npages-nrbpage)*PAGESIZE;
-  nrbpage = npages;
+  set_tm_maxpage(tm_table+t_relocatable,npages);
   rb_limit = rb_end - 2*RB_GETA;
   alloc_page(-(holepage + nrbpage));
   vs_top = vs_base;
@@ -1362,7 +1326,7 @@ DEFUN_NEW("ALLOCATE",object,fSallocate,S
 			make_fixnum(npages));
   tm = tm_of(t);
   if (tm->tm_npage > npages) {npages=tm->tm_npage;}
-  tm->tm_maxpage = npages;
+  set_tm_maxpage(tm,npages);
   if (really_do != Cnil &&
       tm->tm_maxpage > tm->tm_npage)
     goto ALLOCATE;
@@ -1378,8 +1342,7 @@ DEFUN_NEW("ALLOCATE",object,fSallocate,S
       FUNCALL(2,FFN(fSallocate_relocatable_pages)(npages,really_do));
     else {
       
-      if (available_pages < tm->tm_maxpage - tm->tm_npage ||
-	  (pp = alloc_page(tm->tm_maxpage - tm->tm_npage)) == NULL) {
+      if ((pp = alloc_page(tm->tm_maxpage - tm->tm_npage)) == NULL) {
 	FEerror("Can't allocate ~D pages for ~A.", 2,
 		make_fixnum(npages), (make_simple_string(tm->tm_name+1)));
       }
--- gcl-2.6.7+dfsga.orig/o/gmp_big.c
+++ gcl-2.6.7+dfsga/o/gmp_big.c
@@ -538,6 +538,7 @@ coerce_big_to_string(object x, int print
 void
 gcl_init_big(void)
 {
+  gcl_init_big1();
   big_gcprotect=alloc_object(t_bignum);
   MP_SELF(big_gcprotect)=0;
   MP_ALLOCATED(big_gcprotect)=0;
@@ -550,7 +551,6 @@ gcl_init_big(void)
   enter_mark_origin(&big_fixnum2);
   enter_mark_origin(&big_fixnum3);
   enter_mark_origin(&big_fixnum4);
-  gcl_init_big1();
 
 
 }
--- gcl-2.6.7+dfsga.orig/o/main.c
+++ gcl-2.6.7+dfsga/o/main.c
@@ -149,18 +149,68 @@ update_real_maxpage(void) {
       }
   massert(!mbrk(cur));
 
+#ifdef HAVE_SYSCONF_PHYS_PAGES
+  phys_pages=sysconf(_SC_PHYS_PAGES);
+#endif
+
+  available_pages=real_maxpage-first_data_page-resv_pages;
+  for (i=t_start;i<t_other;i++)
+    available_pages-=tm_table[i].tm_type==t_relocatable ? 2*tm_table[i].tm_npage : tm_table[i].tm_maxpage;
+
   return 0;
 
 }
 
+static int
+minimize_image(void) {
+
+#ifdef SGC
+  int in_sgc=sgc_enabled;
+#else
+  int in_sgc=0;
+#endif
+  extern long new_holepage;
+  fixnum old_holepage=new_holepage,i;
+  void *new;
+  
+  if (in_sgc) sgc_quit();
+  holepage=new_holepage=1;
+  GBC(t_contiguous);
+  if (in_sgc) sgc_start();
+  new = (void *)(((((ufixnum)rb_pointer)+ PAGESIZE-1)/PAGESIZE)*PAGESIZE);
+  core_end = new;
+  rb_end=rb_limit=new;
+  set_tm_maxpage(tm_table+t_relocatable,((char *)new-REAL_RB_START)/PAGESIZE);
+  new_holepage=old_holepage;
+  
+#ifdef GCL_GPROF
+  gprof_cleanup();
+#endif
+  
+#if defined(BSD) || defined(ATT)  
+  brk(core_end);
+#endif
+  
+  cbgbccount = tm_table[t_contiguous].tm_adjgbccnt = tm_table[t_contiguous].tm_opt_maxpage = 0;
+  rbgbccount = tm_table[t_relocatable].tm_adjgbccnt = tm_table[t_relocatable].tm_opt_maxpage = 0;
+  for (i = 0;  i < (int)t_end;  i++)
+    tm_table[i].tm_gbccount = tm_table[i].tm_adjgbccnt = tm_table[i].tm_opt_maxpage = 0;
+  
+  return 0;
+  
+}
+
 DEFUN_NEW("SET-LOG-MAXPAGE-BOUND",fixnum,fSset_log_maxpage_bound,SI,1,1,NONE,II,OO,OO,OO,(fixnum l),"") {
 
-  void *end;
+  void *end,*dend;
   fixnum def=sizeof(fixnum)*8-1;
 
   l=l<def ? l : def;
-  end=(void *)(1L<<l);
-  if (end >= (void *)core_end) {
+  end=data_start+(1L<<l)-PAGESIZE;
+  GBC(t_contiguous);
+  dend=heap_end+PAGESIZE+(((rb_pointer-REAL_RB_START)+PAGESIZE-1)&(-PAGESIZE));
+  if (end >= dend) {
+    minimize_image();
     log_maxpage_bound=l;
     update_real_maxpage();
   }
@@ -212,6 +262,7 @@ main(int argc, char **argv, char **envp)
 #include "ld_bind_now.h"
 #endif
 
+
 #if defined(DARWIN)
 	{
 	  extern void init_darwin_zone_compat ();
@@ -383,8 +434,6 @@ main(int argc, char **argv, char **envp)
 	  error("Cannot setup gprof_cleanup on exit");
 #endif
 
-	update_real_maxpage();
-
 	if (initflag) {
 
 #ifdef _WIN32
@@ -1005,7 +1054,6 @@ DEFUN_NEW("LISP-IMPLEMENTATION-VERSION",
 
 static void
 FFN(siLsave_system)(void) {
-  int i;
   
 #ifdef HAVE_YP_UNBIND
   extern object truename(),namestring();
@@ -1025,38 +1073,19 @@ FFN(siLsave_system)(void) {
     
   saving_system = TRUE;
   {
-#ifdef SGC
-    int in_sgc=sgc_enabled;
-#else
-    int in_sgc=0;
-#endif
-    extern long new_holepage;
-    fixnum old_holepage=new_holepage;
-    void *new;
-
-    if (in_sgc) sgc_quit();
-    holepage=new_holepage=1;
-    GBC(t_contiguous);
-    if (in_sgc) sgc_start();
-    new = (void *)(((((ufixnum)rb_pointer)+ PAGESIZE-1)/PAGESIZE)*PAGESIZE);
-    core_end = new;
-    /* rb_end=rb_limit=rb_pointer; */
-    /* nrbpage=(rb_pointer-rb_start)/PAGESIZE; */
-    new_holepage=old_holepage;
+
+    void *old_rb_end=rb_end,*old_rb_limit=rb_limit;
+    fixnum old_nrbpage=nrbpage;
+
+    /* add_pages(tm_table+t_contiguous,1);/\*ensure at least one free contiguous page for starup mallocs*\/ */
+    minimize_image();
+
+    rb_end=old_rb_end;
+    rb_limit=old_rb_limit;
+    set_tm_maxpage(tm_table+t_relocatable,old_nrbpage);
+
   }
 
-#ifdef GCL_GPROF
-  gprof_cleanup();
-#endif
-    
-#if defined(BSD) || defined(ATT)  
-  brk(core_end);
-#endif
-  
-  cbgbccount = tm_table[t_contiguous].tm_adjgbccnt = tm_table[t_contiguous].tm_opt_maxpage = 0;
-  rbgbccount = tm_table[t_relocatable].tm_adjgbccnt = tm_table[t_relocatable].tm_opt_maxpage = 0;
-  for (i = 0;  i < (int)t_end;  i++)
-    tm_table[i].tm_gbccount = tm_table[i].tm_adjgbccnt = tm_table[i].tm_opt_maxpage = 0;
   Lsave();
   saving_system = FALSE;
   alloc_page(-(holepage+nrbpage));
--- gcl-2.6.7+dfsga.orig/o/sgbc.c
+++ gcl-2.6.7+dfsga/o/sgbc.c
@@ -581,7 +581,7 @@ sgc_mark_object1(object x) {
       break;
     if (what_to_collect == t_contiguous) {
       if (!MAYBE_DATA_P((x->cfd.cfd_start)) ||
-	  get_mark_bit(x->cfd.cfd_start))
+	  get_mark_bit(get_pageinfo(x->cfd.cfd_start),x->cfd.cfd_start))
 	break;
       mark_contblock(x->cfd.cfd_start, x->cfd.cfd_size);
     }
@@ -637,24 +637,10 @@ sgc_mark_phase(void) {
       t=v->type;
       tm=tm_of(t);
       p=pagetochar(i);
-      if ( t == t_cons) 
-	for (j = tm->tm_nppage; --j >= 0; p += tm_table[t_cons].tm_size/*  sizeof(struct cons) */) {
-	  object x = (object) p; 
-	  if (SGC_OR_M(x)) 
-	    continue;
-	  /* if (consp(x)) { */
-	  /*   mark(x); */
-	  /*   sgc_mark_cons(x); */
-	  /* } else */
-	  sgc_mark_object1(x);
-	}
-      else {
-	int size=tm->tm_size;
-	for (j = tm->tm_nppage; --j >= 0; p += size) {
-	  object x = (object) p; 
-	  if (SGC_OR_M(x)) continue;
-	  sgc_mark_object1(x);
-	}
+      for (j = tm->tm_nppage; --j >= 0; p += tm->tm_size) {
+	object x = (object) p; 
+	if (SGC_OR_M(x)) continue;
+	sgc_mark_object1(x);
       }
     }
   }
@@ -856,29 +842,29 @@ sgc_contblock_sweep_phase(void) {
     i=page(v);
     j=i+v->in_use;
     
-    s=pagetochar(i);
+    s=pagetochar(i)+mbytes(v->in_use);
     e=(void *)pagetoinfo(j);
 
     for (p = s;  p < e;) {
-      if (get_mark_bit(p)) {
+      if (get_mark_bit(v,p)) {
 	/* SGC cont pages: cont blocks must be no smaller than
 	   sizeof(struct contblock), and must not have a sweep
-	   granularity greater than this amount (e.g. CPTR_ALIGN) if
+	   granularity greater than this amount (e.g. CPTR_SIZE) if
 	   contblock leaks are to be avoided.  Used to be aligned at
 	   PTR_ALIGN. CM 20030827 */
-	p += CPTR_ALIGN;
+	p += CPTR_SIZE;
 	continue;
       }
-      q = p + CPTR_ALIGN;
+      q = p + CPTR_SIZE;
       while (q < e) {
-	if (!get_mark_bit(q)) {
-	  q += CPTR_ALIGN;
+	if (!get_mark_bit(v,q)) {
+	  q += CPTR_SIZE;
 	  continue;
 	}
 	break;
       }
       insert_contblock(p, q - p);
-      p = q + CPTR_ALIGN;
+      p = q + CPTR_SIZE;
     }
     /* i = j + 1; */
   }
@@ -896,7 +882,7 @@ sgc_contblock_sweep_phase(void) {
 #define PAGE_ROUND_UP(adr) \
     ((char *)(PAGESIZE*(((long)(adr)+PAGESIZE -1) >> PAGEWIDTH)))
 
-char *old_rb_start;
+/* char *old_rb_start; */
 
 #undef tm
 
@@ -1191,13 +1177,15 @@ unsigned char *wrimap=NULL;
 int
 sgc_start(void) {
 
-  long i,count,minfree;
+  long i,count,minfree,allocate_more_pages=!saving_system && 10*available_pages>2*(real_maxpage-first_data_page);
   long np;
   struct typemanager *tm;
-  extern int hole_overrun;
   struct pageinfo *v;
+  object omp=sSAoptimize_maximum_pagesA->s.s_dbind;
   double tmp,scale;
 
+  sSAoptimize_maximum_pagesA->s.s_dbind=Cnil;
+  
   if (memprotect_result!=memprotect_success && do_memprotect_test())
     return 0;
 
@@ -1206,22 +1194,20 @@ sgc_start(void) {
 
   /* Reset maxpage statistics if not invoked automatically on a hole
      overrun. 20040804 CM*/
-  if (!hole_overrun) {
-    vs_mark;
-    object *old_vs_base=vs_base;
-    vs_base=vs_top;
-    FFN(siLreset_gbc_count)();
-    vs_base=old_vs_base;
-    vs_reset;
-  }
+  /* if (!hole_overrun) { */
+  /*   vs_mark; */
+  /*   object *old_vs_base=vs_base; */
+  /*   vs_base=vs_top; */
+  /*   FFN(siLreset_gbc_count)(); */
+  /*   vs_base=old_vs_base; */
+  /*   vs_reset; */
+  /* } */
 
   for (i=t_start,scale=1.0,tmp=0.0;i<t_other;i++)
     if (TM_BASE_TYPE_P(i))
       tmp+=WSGC(tm_of(i));
   tmp+=WSGC(tm_of(t_relocatable));
-  /* printf("%lf %ld\n",scale,available_pages/2);fflush(stdout); */
-  scale=tmp>available_pages/2 ? (float)available_pages/(2*tmp) : 1.0;
-  if (scale!=1.0) {printf("%lf %lf %ld\n",scale,tmp,available_pages/2);fflush(stdout);}
+  scale=tmp>available_pages/10 ? (float)available_pages/(10*tmp) : 1.0;
 
   for (i= t_start; i < t_contiguous ; i++) {
     
@@ -1253,7 +1239,7 @@ sgc_start(void) {
       }
 
     /* don't do any more allocations  for this type if saving system */
-    if (saving_system) 
+    if (!allocate_more_pages) 
       continue;
     
     if (count < WSGC(tm)) {
@@ -1294,6 +1280,7 @@ sgc_start(void) {
    pages, especially when the blocks are small as in bignums, makes
    necessary the sweeping of minimal contblocks to prevent leaks. CM
    20030827 */
+
   {
 
     void *p=NULL,*pe;
@@ -1305,8 +1292,8 @@ sgc_start(void) {
 
     for (pi=contblock_list_head;pi;pi=pi->next) {
 
-      j=PAGESIZE*pi->in_use-sizeof(*pi);
-      p=pagetochar(page(pi));
+      j=CB_DATA_SIZE(pi->in_use);
+      p=CB_DATA_START(pi);
       pe=p+j;
 
       for (cbpp=&cb_pointer;*cbpp;cbpp=&(*cbpp)->cb_link)
@@ -1319,16 +1306,14 @@ sgc_start(void) {
       count+=pi->in_use;
 
     }
-    i=WSGC(tm);
-    count=i>count ? i - count : 0;
+    i=allocate_more_pages ? WSGC(tm) : (saving_system ? 1 : 0);
     
-    if (count>0 && !saving_system) {
+    if (i>count) {
       /* SGC cont pages: allocate more if necessary, dumping possible
 	 GBC freed pages onto the old contblock list.  CM 20030827*/
-      unsigned long z=count+1,n=z*PAGESIZE-sizeof(struct pageinfo);
+      unsigned long z=(i-count)+1,n=CB_DATA_SIZE(z);
       void *old_contblock_list_tail=contblock_list_tail;
 
-
       add_pages(tm_table+t_contiguous,n);
 
       massert(old_contblock_list_tail!=contblock_list_tail);
@@ -1347,7 +1332,7 @@ sgc_start(void) {
     
     {
       old_rb_start=rb_start;
-      if(((unsigned long)WSGC(tm)) && !saving_system) {
+      if(((unsigned long)WSGC(tm)) && allocate_more_pages) {
 	new=alloc_relblock(((unsigned long)WSGC(tm))*PAGESIZE);
 	/* the above may cause a gc, shifting the relblock */
 	old_rb_start=rb_start;
@@ -1402,16 +1387,13 @@ sgc_start(void) {
       struct contblock *new_cb_pointer=NULL,*tmp_cb_pointer=NULL,**cbpp;
       void *p=NULL,*pe;
       struct pageinfo *pi;
-      fixnum j;
-
 
       for (pi=contblock_list_head;pi;pi=pi->next) {
 	
 	if (pi->sgc_flags!=SGC_PAGE_FLAG) continue;
 	
-	j=PAGESIZE*pi->in_use-sizeof(*pi);
-	p=pagetochar(page(pi));
-	pe=p+j;
+	p=CB_DATA_START(pi);
+	pe=p+CB_DATA_SIZE(pi->in_use);
 	
 	for (cbpp=&cb_pointer;*cbpp;)
 	  if ((void *)*cbpp>=p && (void *)*cbpp<pe)
@@ -1424,7 +1406,7 @@ sgc_start(void) {
 	cb_pointer=new_cb_pointer;
 	/* SGC contblock pages: add whole pages to new list, p p-k, and
 	   p+i are guaranteed to be distinct when used. CM 20030827 */
-	insert_contblock(pagetochar(page(pi)),pi->in_use*PAGESIZE-sizeof(*pi));
+	insert_contblock(p,pe-p);
 	new_cb_pointer=cb_pointer;
 	cb_pointer=tmp_cb_pointer;
 	
@@ -1488,23 +1470,25 @@ sgc_start(void) {
     fflush(stdout);
   }
 
+  sSAoptimize_maximum_pagesA->s.s_dbind=omp;
+
   return 1;
   
 }
 
-int
-pdebug(void) {
-
-  extern object malloc_list;
-  object x=malloc_list;
-  struct pageinfo *v;
-  for (;x!=Cnil;x=x->c.c_cdr) 
-    printf("%p %d\\n",x->c.c_car->st.st_self,x->c.c_car->st.st_dim);
+/* int */
+/* pdebug(void) { */
 
-  for (v=contblock_list_head;v;v=v->next)
-    printf("%p %d\n",v,v->in_use<<12);
-  return 0;
-}
+/*   extern object malloc_list; */
+/*   object x=malloc_list; */
+/*   struct pageinfo *v; */
+/*   for (;x!=Cnil;x=x->c.c_cdr)  */
+/*     printf("%p %d\n",x->c.c_car->st.st_self,x->c.c_car->st.st_dim); */
+
+/*   for (v=contblock_list_head;v;v=v->next) */
+/*     printf("%p %ld\n",v,v->in_use<<12); */
+/*   return 0; */
+/* } */
 
 
 int
--- gcl-2.6.7+dfsga.orig/o/num_log.c
+++ gcl-2.6.7+dfsga/o/num_log.c
@@ -264,6 +264,9 @@ DEFUN_NEW("1LOGNOT",object,fS1lognot,SI,
   return normalize_big(u);						
   									
 }
+#ifdef STATIC_FUNCTION_POINTERS
+object fS1lognot(object x) { return FFN(fS1lognot)(x);}
+#endif
 
 LFD(Llogior)(void)
 {
--- gcl-2.6.7+dfsga.orig/o/gbc.c
+++ gcl-2.6.7+dfsga/o/gbc.c
@@ -65,31 +65,94 @@ mark_object(object);
    These assume that DBEGIN is divisible by 32, or else we should have
    #define Shamt(x) (((((int) x -DBEGIN) >> 2) & ~(~0 << 5)))
 */ 
-#define BBITS_CHAR 3
+#define LOG_BITS_CHAR 3
 
-#if SIZEOF_LONG == 4
-#define BBYTES_LONG 2
-#elif SIZEOF_LONG == 8
-#define BBYTES_LONG 3
+#if CPTR_SIZE == 8
+#define LOG_BYTES_CONTBLOCK 3
+#elif CPTR_SIZE == 16
+#define LOG_BYTES_CONTBLOCK 4
 #else
-#error Do not recognize SIZEOF_LONG
+#error Do not recognize CPTR_SIZE
 #endif
 
-#if CPTR_ALIGN == 8
-#define BBYTES_CONTBLOCK 3
-#elif CPTR_ALIGN == 16
-#define BBYTES_CONTBLOCK 4
-#else
-#error Do not recognize CPTR_ALIGN
+#ifdef CONTBLOCK_MARK_DEBUG
+int
+cb_check(void) {
+  struct contblock **cbpp;
+  struct pageinfo *v;
+  void *cbe;
+
+  for (cbpp=&cb_pointer;*cbpp;cbpp=&((*cbpp)->cb_link)) {
+    v=get_pageinfo(*cbpp);
+    cbe=((void *)(*cbpp)+(*cbpp)->cb_size-1);
+    if (cbe>(void *)v+v->in_use*PAGESIZE)
+      return 1;
+  }
+  return 0;
+}
+
+int
+m_check(void) {
+  struct contblock **cbpp;
+  void *v,*ve,*p,*pe;
+  extern object malloc_list;
+  object l;
+
+  for (l=malloc_list;l!=Cnil;l=l->c.c_cdr) {
+    p=l->c.c_car->st.st_self;
+    pe=p+l->c.c_car->st.st_dim;
+    for (cbpp=&cb_pointer;*cbpp;cbpp=&((*cbpp)->cb_link)) {
+      v=(void *)(*cbpp);
+      ve=(v+(*cbpp)->cb_size-1);
+      printf("%p %p  %p %p\n",p,pe,v,ve);
+      if ((v<=p && p < ve)||(v<pe && pe<=ve)) 
+	return 1;
+    }
+  }
+  return 0;
+}
+
+int
+off_check(void *v,void *ve,fixnum i,struct pageinfo *pi) {
+  massert(i>=0);
+  massert(v+i<(void *)pi+pi->in_use*PAGESIZE);
+  massert(i<(ve-v));
+  return 0;
+}
 #endif
 
-#define BBITS_LONG (BBYTES_LONG+BBITS_CHAR)
-#define BCHARS_TABLE (BBITS_LONG+BBYTES_CONTBLOCK)
 
-#define Shamt(x) (((((unsigned long) x) >> BBYTES_CONTBLOCK) & ~(~0UL << BBITS_LONG)))
-#define Madr(x) (mark_table+((((unsigned long) x)-(unsigned long)data_start) >> (BCHARS_TABLE)))
-#define get_mark_bit(x) (*(Madr(x)) >> Shamt(x) & 1)
-#define set_mark_bit(x) ((*(Madr(x))) |= (1UL << Shamt(x)))
+#define CB_DATA_SIZE(z_)   ({fixnum _z=(z_);_z*PAGESIZE-mbytes(_z)-sizeof(struct pageinfo);})
+#define CB_MARK_START(pi_) ((void *)(pi_)+sizeof(struct pageinfo))
+#define CB_DATA_START(pi_) ({struct pageinfo *_pi=(pi_);CB_MARK_START(_pi)+mbytes(_pi->in_use);})
+
+inline struct pageinfo *
+get_pageinfo(void *x) {
+  struct pageinfo *v=contblock_list_head;void *vv;
+  for (;(vv=v) && (vv>=x || vv+v->in_use*PAGESIZE<=x);v=v->next);
+  return v;
+}
+
+inline char
+get_mark_bit(struct pageinfo *pi,char *x) {
+  char *v=CB_MARK_START(pi),*ve=CB_DATA_START(pi);
+  fixnum off=(x-ve)>>LOG_BYTES_CONTBLOCK,i=off>>LOG_BITS_CHAR,s=off&~(~0UL<<LOG_BITS_CHAR);
+#ifdef CONTBLOCK_MARK_DEBUG
+  off_check(v,ve,i,pi);
+#endif
+  return (v[i]>>s)&0x1;
+}
+
+inline void
+set_mark_bit(struct pageinfo *pi,char *x) {
+  char *v=CB_MARK_START(pi),*ve=CB_DATA_START(pi);
+  fixnum off=(x-ve)>>LOG_BYTES_CONTBLOCK,i=off>>LOG_BITS_CHAR,s=off&~(~0UL<<LOG_BITS_CHAR);
+#ifdef CONTBLOCK_MARK_DEBUG
+  off_check(v,ve,i,pi);
+#endif
+  v[i]|=(1UL<<s);
+}
+
 
 #ifdef KCLOVM
 void mark_all_stacks();
@@ -107,18 +170,8 @@ int sgc_enabled=0;
 #endif
 long  first_protectable_page =0;
 
-
-
 static char *copy_relblock(char *p, int s);
 
-
-
-#ifdef MV
-
-
-#endif
-
-
 long real_maxpage;
 long new_holepage;
 
@@ -138,46 +191,17 @@ object sSAgbc_messageA;
 #define	MARK_ORIGIN_MAX		300
 #define	MARK_ORIGIN_BLOCK_MAX	20
 
-#ifdef AV
-/*
-  See bitop.c.
-*/
-#endif
-#ifdef MV
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#endif
-
-/* #define	symbol_marked(x)	((x)->d.m) */
-
 object *mark_origin[MARK_ORIGIN_MAX];
 int mark_origin_max;
 
 struct {
-  object	*mob_addr;	/*  mark origin block address  */
+  object *mob_addr;	/*  mark origin block address  */
   int	mob_size;	/*  mark origin block size  */
 } mark_origin_block[MARK_ORIGIN_BLOCK_MAX];
 int mark_origin_block_max;
 
-/* must be a long * to match with SIZEOF_LONG usage above*/
-long *mark_table;
-
 enum type what_to_collect;
 
-
-
 void
 enter_mark_origin(object *p) {
 
@@ -188,39 +212,6 @@ enter_mark_origin(object *p) {
 
 }
 
-/* static void */
-/* mark_cons(object x) { */
-  
-/*   cs_check(x); */
-  
-/*   /\*  x is already marked.  *\/ */
-  
-/*  BEGIN:   */
-/*   if (NULL_OR_ON_C_STACK(x->c.c_car)) goto MARK_CDR; */
-/*   if (type_of(x->c.c_car) == t_cons) { */
-/*     if (is_marked_or_free(x->c.c_car)) */
-/*       ; */
-/*     else { */
-/*       mark(x->c.c_car); */
-/*       mark_cons(x->c.c_car); */
-/*     } */
-/*   } else */
-/*     mark_object(x->c.c_car); */
-/*  MARK_CDR:   */
-/*   if (NULL_OR_ON_C_STACK(x->c.c_cdr)) */
-/*     return; */
-/*   x = Scdr(x); */
-/*   if (consp(x)) { */
-/*     if (is_marked_or_free(x)) */
-/*       return; */
-/*     mark(x); */
-/*     goto BEGIN; */
-/*   } */
-/*   if (x == Cnil) */
-/*     return; */
-/*   mark_object(x); */
-/* } */
-
 static void
 mark_cons(object x) {
   
@@ -638,7 +629,7 @@ mark_object(object x) {
       break;
     if (what_to_collect == t_contiguous) {
       if (!MAYBE_DATA_P((x->cfd.cfd_start)) ||
-	  get_mark_bit((long *)(x->cfd.cfd_start)))
+	  get_mark_bit(get_pageinfo(x->cfd.cfd_start),x->cfd.cfd_start))
 	break;
       mark_contblock(x->cfd.cfd_start, x->cfd.cfd_size);}
     break;
@@ -908,7 +899,7 @@ mark_c_stack(jmp_buf env1, int n, void (
 	  tv=pagetoinfo(page(v)+i);
 	  if (PAGEINFO_P(tv)) {
 	    a=contblock_stack_list;
-	    printf("%p\n",tv);
+	    /* printf("%p\n",tv); */
 	    contblock_stack_list=alloca(2*sizeof(a));
 	    contblock_stack_list[0]=tv;
 	    contblock_stack_list[1]=a;
@@ -991,7 +982,7 @@ sweep_phase(void) {
 	unmark(x);
 	continue;
       }
-      
+
 #ifdef GMP_USE_MALLOC
       if (x->d.t == t_bignum) {
 	mpz_clear(MP(x));
@@ -1028,29 +1019,29 @@ contblock_sweep_phase(void) {
 
   for (v=contblock_list_head;v;v=v->next) {
 
-    s=pagetochar(page(v));
-    e=(void *)pagetoinfo(page(s)+v->in_use);
+    s=CB_DATA_START(v);
+    e=(void *)v+v->in_use*PAGESIZE;
 
     for (p = s;  p < e;) {
-      if (get_mark_bit(p)) {
+      if (get_mark_bit(v,p)) {
 	/* SGC cont pages: cont blocks must be no smaller than
 	   sizeof(struct contblock), and must not have a sweep
-	   granularity greater than this amount (e.g. CPTR_ALIGN) if
+	   granularity greater than this amount (e.g. CPTR_SIZE) if
 	   contblock leaks are to be avoided.  Used to be aligned at
 	   PTR_ALIGN. CM 20030827 */
-	p += CPTR_ALIGN;
+	p += CPTR_SIZE;
 	continue;
       }
-      q = p + CPTR_ALIGN;
+      q = p + CPTR_SIZE;
       while (q < e) {
-	if (!get_mark_bit(q)) {
-	  q += CPTR_ALIGN;
+	if (!get_mark_bit(v,q)) {
+	  q += CPTR_SIZE;
 	  continue;
 	}
 	break;
       }
       insert_contblock(p, q - p);
-      p = q + CPTR_ALIGN;
+      p = q + CPTR_SIZE;
     }
   }
 #ifdef DEBUG
@@ -1091,7 +1082,7 @@ fixnum fault_pages=0;
 void
 GBC(enum type t) {
 
-  long i, j;
+  long i,j;
   struct apage *pp, *qq;
 #ifdef SGC
   int in_sgc = sgc_enabled;
@@ -1155,21 +1146,18 @@ GBC(enum type t) {
   maxpage = page(heap_end);
   
   if ((int)t >= (int)t_contiguous) {
-    j = (maxpage-first_data_page)*(PAGESIZE/(CPTR_ALIGN*SIZEOF_LONG*CHAR_SIZE)) ;
-    
-    if (t == t_relocatable)
-      j = 0;
+
+    /* j = (maxpage-first_data_page)*(PAGESIZE/(CPTR_SIZE*SIZEOF_LONG*CHAR_SIZE)) ; */
     
-#ifdef SGC
-    i = rb_pointer - (sgc_enabled ? old_rb_start : rb_start);
-#else
-    i = rb_pointer - rb_start;
-#endif    
+    /* if (t == t_relocatable) */
+    /*   j = 0; */
+
+    i=rb_pointer-REAL_RB_START;
 
 #ifdef SGC
-      if (sgc_enabled==0)
+    if (sgc_enabled==0)
 #endif
-	{rb_start = heap_end + PAGESIZE*holepage;}
+      rb_start = heap_end + PAGESIZE*holepage;
     
     rb_end = heap_end + (holepage + nrbpage) *PAGESIZE;
     
@@ -1190,16 +1178,25 @@ GBC(enum type t) {
     rb_pointer = rb_start;  /* where the new relblock will start */
     rb_pointer1 = rb_start1;/* where we will copy it to during gc*/
     
-    mark_table = (long *)(rb_start1 + i);
+    /* mark_table = (long *)(rb_start1 + i); */
     
-    if (rb_end < (char *)&mark_table[j])
-      i = (char *)&mark_table[j] - heap_end;
+    if (rb_end < (rb_start1 + i))/*(char *)&mark_table[j]*/
+      i = (rb_start1 + i) - heap_end;
     else
       i = rb_end - heap_end;
     alloc_page(-(i + PAGESIZE - 1)/PAGESIZE);
     
-    for (i = 0;  i < j; i++)
-      mark_table[i] = 0;
+    /* for (i = 0;  i < j; i++) */
+    /*   mark_table[i] = 0; */
+    
+    { 
+      struct pageinfo *v;
+      for (v=contblock_list_head;v;v=v->next) {
+	void *p=pagetochar(page(v)),*pe=p+mbytes(v->in_use);
+	bzero(p,pe-p);
+      }
+    }
+
   }
   
 #ifdef DEBUG
@@ -1352,13 +1349,12 @@ GBC(enum type t) {
   }
   
   {
-    extern int hole_overrun;
     extern long opt_maxpage(struct typemanager *);
 
 #define IGNORE_MAX_PAGES (sSAignore_maximum_pagesA ==0 || sSAignore_maximum_pagesA->s.s_dbind !=sLnil) 
 #define OPTIMIZE_MAX_PAGES (sSAoptimize_maximum_pagesA ==0 || sSAoptimize_maximum_pagesA->s.s_dbind !=sLnil) 
 
-    if (!hole_overrun && IGNORE_MAX_PAGES && OPTIMIZE_MAX_PAGES)
+    if (IGNORE_MAX_PAGES && OPTIMIZE_MAX_PAGES)
       opt_maxpage(tm_table+t);
     
   }
@@ -1476,6 +1472,7 @@ mark_contblock(void *p, int s) {
 
   STATIC char *q;
   STATIC char *x, *y;
+  struct pageinfo *v;
   
   if (!MAYBE_DATA_P(p))
     return;
@@ -1484,8 +1481,12 @@ mark_contblock(void *p, int s) {
      sizeof(struct contblock).  CM 20030827 */
   x = (char *)ROUND_DOWN_PTR_CONT(p);
   y = (char *)ROUND_UP_PTR_CONT(q);
-  for (;  x < y;  x+=CPTR_ALIGN)
-    set_mark_bit(x);
+  v=get_pageinfo(x);
+#ifdef SGC
+  if (!sgc_enabled || (v->sgc_flags&SGC_PAGE_FLAG))
+#endif
+    for (;  x < y;  x+=CPTR_SIZE)
+      set_mark_bit(v,x);
 }
 
 DEFUN_NEW("GBC",object,fLgbc,LISP
