From 723055bbf736ff514c3a7b4092dd3ebecf0be428 Mon Sep 17 00:00:00 2001
From: toy <toy>
Date: Fri, 9 Jan 2004 05:07:39 +0000
Subject: [PATCH] Update to sparc gencgc so that alloc-tn holds the
 current-region-free-pointer.

Cross compile may be needed, but I'm not sure.  I only used
cross-compiling to do this change.

sparc/macros.lisp:
o Update the allocation macro appropriately for alloc-tn holding the
  current-region-free-pointer.

lisp/gencgc.c:
o Define macros for setting and getting *current-region-free-oointer*
  and *current-region-end-addr* so sparc can use alloc-tn.
  *current-region-free-pointer* isn't used anymore, but is still a
  static symbol.  It's been replaced by alloc-tn.
o On sparc, set_alloc_pointer doesn't need to do anything anymore.
o Don't need to call update_dynamic_space_free_pointer anymore.
o The assertion that *current-region-free-pointer* is a fixnum is no
  longer valid on sparc because that is alloc-tn which contains the
  pseudo-atomic bits.

lisp/sparc-arch.c:
o The allocation trap instruction is now preceeded by a SUB
  instruction.  Handle that correctly.  Keep support for the OR
  instruction for now, but should be removed.
o Set alloc-tn from current_dynamic_space_free_pointer.
---
 compiler/sparc/macros.lisp |  34 ++++++++++--
 lisp/gencgc.c              | 111 +++++++++++++++++++++++++++----------
 lisp/sparc-arch.c          |  73 +++++++++++++++++-------
 3 files changed, 166 insertions(+), 52 deletions(-)

diff --git a/compiler/sparc/macros.lisp b/compiler/sparc/macros.lisp
index 23559bc51..9f290f829 100644
--- a/compiler/sparc/macros.lisp
+++ b/compiler/sparc/macros.lisp
@@ -5,11 +5,11 @@
 ;;; Carnegie Mellon University, and has been placed in the public domain.
 ;;;
 (ext:file-comment
-  "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/macros.lisp,v 1.29 2003/12/03 17:52:17 toy Exp $")
+  "$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/macros.lisp,v 1.30 2004/01/09 05:07:39 toy Exp $")
 ;;;
 ;;; **********************************************************************
 ;;;
-;;; $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/macros.lisp,v 1.29 2003/12/03 17:52:17 toy Exp $
+;;; $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/macros.lisp,v 1.30 2004/01/09 05:07:39 toy Exp $
 ;;;
 ;;; This file contains various useful macros for generating SPARC code.
 ;;;
@@ -236,7 +236,7 @@
 		(inst andn ,result-tn alloc-tn lowtag-mask)
 		(inst or ,result-tn ,lowtag)
 		(inst add alloc-tn ,size))))
-	 #+gencgc
+	 #+nil
 	 (t
 	  (let ((done (gen-label))
 		(full-alloc (gen-label)))
@@ -272,7 +272,33 @@
 	      
 	    (emit-label done)
 	    ;; Set lowtag appropriately
-	    (inst or ,result-tn ,lowtag)))))
+	    (inst or ,result-tn ,lowtag)))
+	 #+gencgc
+	 (t
+	  ;; See if we can do an inline allocation.  The updated
+	  ;; free pointer should not point past the end of the
+	  ;; current region.  If it does, a full alloc needs to be
+	  ;; done.
+	  (load-symbol-value ,result-tn *current-region-end-addr*)
+	  (inst add alloc-tn ,size)	; Point to end
+	  (inst andn ,temp-tn alloc-tn lowtag-mask) ; Zap PA bits
+	      
+	  ;; temp-tn points to the new end of region.  Did we go
+	  ;; past the actual end of the region?  If so, we need a
+	  ;; full alloc.
+	  (inst cmp ,temp-tn ,result-tn)
+	  (without-scheduling ()
+	    ;; NOTE: alloc-tn has been updated to point to the new
+	    ;; end.  But the allocation routines expect alloc-tn
+	    ;; points to original free region.  Thus, the allocation
+	    ;; trap handler MUST subtract SIZE from alloc-tn before
+	    ;; calling the alloc routine.  This allows for
+	    ;; (slightly) faster code for inline allocation.
+	    (inst sub ,result-tn ,temp-tn ,size) ; Set result-tn to old alloc-tn, minus PA
+	    (inst t :gt allocation-trap))
+	  ;; Set lowtag appropriately
+	  (inst or ,result-tn ,lowtag))
+	 ))
 
 
 (defmacro with-fixed-allocation ((result-tn temp-tn type-code size
diff --git a/lisp/gencgc.c b/lisp/gencgc.c
index 1b0e8ab02..8a083c5c5 100644
--- a/lisp/gencgc.c
+++ b/lisp/gencgc.c
@@ -7,7 +7,7 @@
  *
  * Douglas Crosher, 1996, 1997, 1998, 1999.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.46 2003/10/24 02:57:00 toy Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.47 2004/01/09 05:07:39 toy Exp $
  *
  */
 
@@ -47,6 +47,16 @@
 #define clr_pseudo_atomic_interrupted() \
   SetSymbolValue (PSEUDO_ATOMIC_INTERRUPTED, make_fixnum (0))
 
+#define set_current_region_free(value) \
+  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (value))
+#define set_current_region_end(value) \
+  SetSymbolValue(CURRENT_REGION_END_ADDR, (value))
+#define get_current_region_free() \
+  SymbolValue(CURRENT_REGION_FREE_POINTER)
+
+#define set_current_region_end(value) \
+  SetSymbolValue(CURRENT_REGION_END_ADDR, (value))
+
 #elif defined(sparc)
 
 /*
@@ -54,9 +64,13 @@
  * stuff, so we need to preserve those bits when we give it a value.
  * This value better not have any bits set there either!
  */
+#if 0
 #define set_alloc_pointer(value) \
   (current_dynamic_space_free_pointer = (lispobj*) ((value) \
          | ((unsigned long) current_dynamic_space_free_pointer & lowtag_Mask)))
+#else
+#define set_alloc_pointer(value) 
+#endif
 #define get_alloc_pointer() \
   ((unsigned long) current_dynamic_space_free_pointer & ~lowtag_Mask)
 #define get_binding_stack_pointer() \
@@ -75,6 +89,24 @@
   (current_dynamic_space_free_pointer \
    = (lispobj*) ((unsigned long) current_dynamic_space_free_pointer & ~pseudo_atomic_InterruptedValue))
 
+#if 0
+#define set_current_region_free(value) \
+  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (value))
+
+#define get_current_region_free() \
+  SymbolValue(CURRENT_REGION_FREE_POINTER)
+
+#else
+#define set_current_region_free(value) \
+  current_dynamic_space_free_pointer = (lispobj*)((value) | ((long)current_dynamic_space_free_pointer & lowtag_Mask))
+
+#define get_current_region_free() \
+  ((long)current_dynamic_space_free_pointer & (~(lowtag_Mask)))
+#endif
+
+#define set_current_region_end(value) \
+  SetSymbolValue(CURRENT_REGION_END_ADDR, (value))
+
 #else
 #error gencgc is not supported on this platform
 #endif
@@ -835,7 +867,11 @@ static void gc_alloc_new_region(int nbytes, int unboxed,
 
     /* Check for a failure */
     if (first_page >= dynamic_space_pages - reserved_heap_pages) {
+#if 0
       handle_heap_overflow("*A2 gc_alloc_new_region failed, nbytes=%d.\n", nbytes);
+#else
+      break;
+#endif
     }
 
     gc_assert(!PAGE_WRITE_PROTECTED(first_page));
@@ -877,6 +913,10 @@ static void gc_alloc_new_region(int nbytes, int unboxed,
   }
   while (restart_page < dynamic_space_pages && bytes_found < nbytes);
 
+  if (first_page >= dynamic_space_pages - reserved_heap_pages) {
+    handle_heap_overflow("*A2 gc_alloc_new_region failed, nbytes=%d.\n", nbytes);
+  }
+  
   /* Check for a failure */
   if (restart_page >= (dynamic_space_pages - reserved_heap_pages) && bytes_found < nbytes) {
     handle_heap_overflow("*A1 gc_alloc_new_region failed, nbytes=%d.\n", nbytes);
@@ -1275,9 +1315,12 @@ static void *gc_alloc_large(int  nbytes, int unboxed,
 
     /* Check for a failure */
     if (first_page >= dynamic_space_pages - reserved_heap_pages) {
+#if 0
       handle_heap_overflow("*A2 gc_alloc_large failed, nbytes=%d.\n", nbytes);
+#else
+      break;
+#endif
     }
-
     gc_assert(!PAGE_WRITE_PROTECTED(first_page));
 
 #if 0
@@ -1311,6 +1354,10 @@ static void *gc_alloc_large(int  nbytes, int unboxed,
   }
   while ((restart_page < dynamic_space_pages) && (bytes_found < nbytes));
 
+  if (first_page >= dynamic_space_pages - reserved_heap_pages) {
+    handle_heap_overflow("*A2 gc_alloc_large failed, nbytes=%d.\n", nbytes);
+  }
+  
   /* Check for a failure */
   if (restart_page >= (dynamic_space_pages - reserved_heap_pages) && bytes_found < nbytes) {
     handle_heap_overflow("*A1 gc_alloc_large failed, nbytes=%d.\n", nbytes);
@@ -6157,14 +6204,13 @@ void gencgc_verify_zero_fill(void)
 {
   /* Flush the alloc regions updating the tables. */
   
-  boxed_region.free_pointer = (void *) SymbolValue(CURRENT_REGION_FREE_POINTER);
+  boxed_region.free_pointer = (void *) get_current_region_free();
   gc_alloc_update_page_tables(0, &boxed_region);
   gc_alloc_update_page_tables(1, &unboxed_region);
   fprintf(stderr, "* Verifying zero fill\n");
   verify_zero_fill();
-  SetSymbolValue(CURRENT_REGION_FREE_POINTER,
-		 (lispobj)boxed_region.free_pointer);
-  SetSymbolValue(CURRENT_REGION_END_ADDR, (lispobj)boxed_region.end_addr);
+  set_current_region_free((lispobj)boxed_region.free_pointer);
+  set_current_region_end((lispobj)boxed_region.end_addr);
 }
 
 static void verify_dynamic_space(void)
@@ -6533,7 +6579,7 @@ void	collect_garbage(unsigned last_gen)
   int gen_to_wp;
   int i;
 
-  boxed_region.free_pointer = (void *) SymbolValue(CURRENT_REGION_FREE_POINTER);
+  boxed_region.free_pointer = (void *) get_current_region_free();
 
   /* Check last_gen */
   if (last_gen > NUM_GENERATIONS) {
@@ -6641,10 +6687,15 @@ void	collect_garbage(unsigned last_gen)
   gc_assert(boxed_region.free_pointer - boxed_region.start_addr == 0);
   gc_alloc_generation = 0;
 
+  /* Sparc doesn't need this because the dynamic space free pointer is
+     the same as the current region free pointer, which is updated by
+     the allocation routines appropriately. */
+#if !defined(sparc)
   update_dynamic_space_free_pointer();
-
-  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (lispobj) boxed_region.free_pointer);
-  SetSymbolValue(CURRENT_REGION_END_ADDR, (lispobj) boxed_region.end_addr);
+#endif
+  
+  set_current_region_free((lispobj) boxed_region.free_pointer);
+  set_current_region_end((lispobj) boxed_region.end_addr);
 
   /* Call the scavenger hook functions */
   {
@@ -6757,8 +6808,8 @@ void	gc_free_heap(void)
 
   set_alloc_pointer((lispobj) heap_base);
   
-  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (lispobj) boxed_region.free_pointer);
-  SetSymbolValue(CURRENT_REGION_END_ADDR, (lispobj) boxed_region.end_addr);
+  set_current_region_free((lispobj) boxed_region.free_pointer);
+  set_current_region_end((lispobj) boxed_region.end_addr);
 
   if (verify_after_free_heap) {
     /* Check if purify has left any bad pointers. */
@@ -6833,8 +6884,8 @@ void gc_init(void)
 
   last_free_page = 0;
 
-  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (lispobj) boxed_region.free_pointer);
-  SetSymbolValue(CURRENT_REGION_END_ADDR, (lispobj) boxed_region.end_addr);
+  set_current_region_free((lispobj) boxed_region.free_pointer);
+  set_current_region_end((lispobj) boxed_region.end_addr);
 }
 
 /*
@@ -6867,8 +6918,8 @@ void	gencgc_pickup_dynamic(void)
   generations[0].bytes_allocated = PAGE_SIZE * page;
   bytes_allocated = PAGE_SIZE * page;
 
-  SetSymbolValue(CURRENT_REGION_FREE_POINTER, (lispobj) boxed_region.free_pointer);
-  SetSymbolValue(CURRENT_REGION_END_ADDR, (lispobj) boxed_region.end_addr);
+  set_current_region_free((lispobj) boxed_region.free_pointer);
+  set_current_region_end((lispobj) boxed_region.end_addr);
 }
 
 
@@ -6897,7 +6948,9 @@ void do_pending_interrupt (void);
 char *
 alloc (int nbytes)
 {
-  gc_assert (((unsigned) SymbolValue (CURRENT_REGION_FREE_POINTER) & lowtag_Mask) == 0);
+#ifndef sparc
+  gc_assert (((unsigned) get_current_region_free() & lowtag_Mask) == 0);
+#endif
   gc_assert ((nbytes & lowtag_Mask) == 0);
   gc_assert (get_pseudo_atomic_atomic ());
 
@@ -6907,26 +6960,24 @@ alloc (int nbytes)
     {
       void *new_obj;
       char *new_free_pointer
-  	= (void *) (SymbolValue (CURRENT_REGION_FREE_POINTER) + nbytes);
+  	= (void *) (get_current_region_free() + nbytes);
 	  
       if (new_free_pointer <= boxed_region.end_addr)
 	{
 	  /* Allocate from the current region. */
-	  new_obj = (void *) SymbolValue (CURRENT_REGION_FREE_POINTER);
-	  SetSymbolValue (CURRENT_REGION_FREE_POINTER,
-			  (lispobj) new_free_pointer);
+	  new_obj = (void *) get_current_region_free();
+	  set_current_region_free((lispobj) new_free_pointer);
 	  return new_obj;
 	}
       else if (bytes_allocated <= auto_gc_trigger)
 	{
 	  /* Call gc_alloc.  */
-	  boxed_region.free_pointer
-	    = (void *) SymbolValue (CURRENT_REGION_FREE_POINTER);
+	  boxed_region.free_pointer = (void *) get_current_region_free();
+          boxed_region.end_addr = (void *) SymbolValue(CURRENT_REGION_END_ADDR);
+          
 	  new_obj = gc_alloc (nbytes);
-	  SetSymbolValue (CURRENT_REGION_FREE_POINTER,
-			  (lispobj) boxed_region.free_pointer);
-	  SetSymbolValue (CURRENT_REGION_END_ADDR,
-			  (lispobj) boxed_region.end_addr);
+	  set_current_region_free((lispobj) boxed_region.free_pointer);
+	  set_current_region_end((lispobj) boxed_region.end_addr);
 	  return new_obj;
 	}
       else
@@ -7013,9 +7064,13 @@ int get_bytes_consed_upper(void)
   return ((int)bytes_allocated_sum / 0x10000000) & 0xFFFFFFF;
 }
 
+#if 0
 #define current_region_free_pointer SymbolValue(CURRENT_REGION_FREE_POINTER)
 #define current_region_end_addr     ((void *) SymbolValue(CURRENT_REGION_END_ADDR))
-
+#else
+#define current_region_free_pointer get_current_region_free()
+#define current_region_end_addr     ((void *) SymbolValue(CURRENT_REGION_END_ADDR))
+#endif
 int get_bytes_allocated_lower(void)
 {
   int size = bytes_allocated;
diff --git a/lisp/sparc-arch.c b/lisp/sparc-arch.c
index 6a5b9f9aa..706a644f0 100644
--- a/lisp/sparc-arch.c
+++ b/lisp/sparc-arch.c
@@ -1,6 +1,6 @@
 /*
 
- $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sparc-arch.c,v 1.19 2003/10/24 02:57:00 toy Exp $
+ $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sparc-arch.c,v 1.20 2004/01/09 05:07:39 toy Exp $
 
  This code was written as part of the CMU Common Lisp project at
  Carnegie Mellon University, and has been placed in the public domain.
@@ -244,9 +244,11 @@ boolean allocation_trap_p(struct sigcontext *context)
   
   if (trap_inst_p(pc, &trapno) && (trapno == trap_Allocation))
     {
-      /* Got the trap.  Is it preceeded by an OR instruction? */
+      /* Got the trap.  Is it preceeded by an OR instruction or SUB
+         instruction? */
       or_inst = pc[-1];
-      if (((or_inst >> 30) == 2) && (((or_inst >> 19) & 0x1f) == 2))
+      if ((((or_inst >> 30) == 2) && (((or_inst >> 19) & 0x1f) == 2)) ||
+          (((or_inst >> 30) == 2) && (((or_inst >> 19) & 0x1f) == 4)))
         {
           result = 1;
         }
@@ -278,7 +280,7 @@ void handle_allocation_trap(struct sigcontext *context)
 {
   unsigned int* pc;
   unsigned int or_inst;
-  int rs1;
+  int target;
   int size;
   int immed;
   int context_index;
@@ -301,27 +303,50 @@ void handle_allocation_trap(struct sigcontext *context)
 
   /*
    * The instruction before this trap instruction had better be an OR
-   * instruction!
+   * instruction or SUB instruction!
    */
 
-  /*
-   * An OR instruction.  RS1 is the register we want to allocate to.
-   * RS2 (or an immediate) is the size.
-   */
+  if (((or_inst >> 30) == 2) && (((or_inst >> 19) & 0x1f) == 2))
+    {
+      /*
+       * An OR instruction.  RS1 is the register we want to allocate
+       * to.  RS2 (or an immediate) is the size.
+       */
 
-  rs1 = (or_inst >> 14) & 0x1f;
+      target = (or_inst >> 14) & 0x1f;
       
-  immed = (or_inst >> 13) & 1;
+      immed = (or_inst >> 13) & 1;
 
-  if (immed == 1)
-    {
-      size = or_inst & 0x1fff;
+      if (immed == 1)
+        {
+          size = or_inst & 0x1fff;
+        }
+      else
+        {
+          size = or_inst & 0x1f;
+          size = SC_REG(context, size);
+        }
     }
-  else
+  else if (((or_inst >> 30) == 2) && (((or_inst >> 19) & 0x1f) == 4))
     {
-      size = or_inst & 0x1f;
-      size = SC_REG(context, size);
+      /*
+       * A SUB instruction.  RD is the register to allocate to, RS2
+       * (or an immediate) is the size.
+       */
+     
+      target = (or_inst >> 25) & 0x1f;
+      immed = (or_inst >> 13) & 1;
+      if (immed == 1)
+        {
+          size = or_inst & 0x1fff;
+        }
+      else
+        {
+          size = or_inst & 0x1f;
+          size = SC_REG(context, size);
+        }
     }
+  
 
   /*
    * I don't think it's possible for us NOT to be in lisp when we get
@@ -337,17 +362,25 @@ void handle_allocation_trap(struct sigcontext *context)
     {
       fprintf(stderr, "**** Whoa! allocation trap and we weren't in lisp!\n");
     }
+
+  /*
+   * alloc-tn was incremented by size.  If we get here, we need to
+   * decrement it by size to restore it's original value.
+   */
+  /*  current_dynamic_space_free_pointer = (lispobj *) SC_REG(context, reg_ALLOC);*/
+  current_dynamic_space_free_pointer = (lispobj*) ((long)current_dynamic_space_free_pointer - size);
   
   /*
-   * Allocate some memory, store the memory address in rs1.
+   * Allocate some memory, store the memory address in target.
    */
 
 #if 0
-  fprintf(stderr, "Alloc %d to %s\n", size, lisp_register_names[rs1]);
+  fprintf(stderr, "Alloc %d to %s\n", size, lisp_register_names[target]);
 #endif
 
   memory = (char *) alloc(size);
-  SC_REG(context, rs1) = (unsigned long) memory;
+  SC_REG(context, target) = (unsigned long) memory;
+  SC_REG(context, reg_ALLOC) = current_dynamic_space_free_pointer;
 
   if (were_in_lisp)
     {
-- 
GitLab