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