0.8.12.36:
[sbcl.git] / src / runtime / gencgc.c
index 47eb8f3..ea90e34 100644 (file)
@@ -68,6 +68,20 @@ boolean interrupt_maybe_gc_int(int, siginfo_t *, void *);
  * that don't have pointers to younger generations? */
 boolean enable_page_protection = 1;
 
+/* Should we unmap a page and re-mmap it to have it zero filled? */
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+/* comment from cmucl-2.4.8: This can waste a lot of swap on FreeBSD
+ * so don't unmap there.
+ *
+ * The CMU CL comment didn't specify a version, but was probably an
+ * old version of FreeBSD (pre-4.0), so this might no longer be true.
+ * OTOH, if it is true, this behavior might exist on OpenBSD too, so
+ * for now we don't unmap there either. -- WHN 2001-04-07 */
+boolean gencgc_unmap_zero = 0;
+#else
+boolean gencgc_unmap_zero = 1;
+#endif
+
 /* the minimum size (in bytes) for a large object*/
 unsigned large_object_size = 4 * PAGE_BYTES;
 
@@ -80,7 +94,11 @@ unsigned large_object_size = 4 * PAGE_BYTES;
 
 /* the verbosity level. All non-error messages are disabled at level 0;
  * and only a few rare messages are printed at level 1. */
-unsigned gencgc_verbose = (QSHOW ? 1 : 0);
+#ifdef QSHOW
+unsigned gencgc_verbose = 1;
+#else
+unsigned gencgc_verbose = 0;
+#endif
 
 /* FIXME: At some point enable the various error-checking things below
  * and see what they say. */
@@ -139,7 +157,7 @@ static void *heap_base = NULL;
 
 
 /* Calculate the start address for the given page number. */
-static inline void *
+inline void *
 page_address(int page_num)
 {
     return (heap_base + (page_num * PAGE_BYTES));
@@ -281,7 +299,7 @@ count_generation_pages(int generation)
     return count;
 }
 
-#if QSHOW
+#ifdef QSHOW
 static int
 count_dont_move_pages(void)
 {
@@ -1415,7 +1433,7 @@ sniff_code_object(struct code *code, unsigned displacement)
        unsigned d2 = *((unsigned char *)p - 2);
        unsigned d3 = *((unsigned char *)p - 3);
        unsigned d4 = *((unsigned char *)p - 4);
-#if QSHOW
+#ifdef QSHOW
        unsigned d5 = *((unsigned char *)p - 5);
        unsigned d6 = *((unsigned char *)p - 6);
 #endif
@@ -1937,64 +1955,34 @@ scav_weak_pointer(lispobj *where, lispobj object)
 }
 
 \f
-/* Scan an area looking for an object which encloses the given pointer.
- * Return the object start on success or NULL on failure. */
-static lispobj *
-search_space(lispobj *start, size_t words, lispobj *pointer)
-{
-    while (words > 0) {
-       size_t count = 1;
-       lispobj thing = *start;
-
-       /* If thing is an immediate then this is a cons. */
-       if (is_lisp_pointer(thing)
-           || ((thing & 3) == 0) /* fixnum */
-           || (widetag_of(thing) == BASE_CHAR_WIDETAG)
-           || (widetag_of(thing) == UNBOUND_MARKER_WIDETAG))
-           count = 2;
-       else
-           count = (sizetab[widetag_of(thing)])(start);
-
-       /* Check whether the pointer is within this object. */
-       if ((pointer >= start) && (pointer < (start+count))) {
-           /* found it! */
-           /*FSHOW((stderr,"/found %x in %x %x\n", pointer, start, thing));*/
-           return(start);
-       }
-
-       /* Round up the count. */
-       count = CEILING(count,2);
-
-       start += count;
-       words -= count;
-    }
-    return (NULL);
-}
-
-lispobj*
-search_read_only_space(lispobj *pointer)
+lispobj *
+search_read_only_space(void *pointer)
 {
-    lispobj* start = (lispobj*)READ_ONLY_SPACE_START;
-    lispobj* end = (lispobj*)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0);
-    if ((pointer < start) || (pointer >= end))
+    lispobj *start = (lispobj *) READ_ONLY_SPACE_START;
+    lispobj *end = (lispobj *) SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0);
+    if ((pointer < (void *)start) || (pointer >= (void *)end))
        return NULL;
-    return (search_space(start, (pointer+2)-start, pointer));
+    return (search_space(start, 
+                        (((lispobj *)pointer)+2)-start, 
+                        (lispobj *) pointer));
 }
 
 lispobj *
-search_static_space(lispobj *pointer)
+search_static_space(void *pointer)
 {
-    lispobj* start = (lispobj*)STATIC_SPACE_START;
-    lispobj* end = (lispobj*)SymbolValue(STATIC_SPACE_FREE_POINTER,0);
-    if ((pointer < start) || (pointer >= end))
+    lispobj *start = (lispobj *)STATIC_SPACE_START;
+    lispobj *end = (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0);
+    if ((pointer < (void *)start) || (pointer >= (void *)end))
        return NULL;
-    return (search_space(start, (pointer+2)-start, pointer));
+    return (search_space(start, 
+                        (((lispobj *)pointer)+2)-start, 
+                        (lispobj *) pointer));
 }
 
 /* a faster version for searching the dynamic space. This will work even
  * if the object is in a current allocation region. */
 lispobj *
-search_dynamic_space(lispobj *pointer)
+search_dynamic_space(void *pointer)
 {
     int page_index = find_page_index(pointer);
     lispobj *start;
@@ -2005,7 +1993,9 @@ search_dynamic_space(lispobj *pointer)
        return NULL;
     start = (lispobj *)((void *)page_address(page_index)
                        + page_table[page_index].first_object_offset);
-    return (search_space(start, (pointer+2)-start, pointer));
+    return (search_space(start, 
+                        (((lispobj *)pointer)+2)-start, 
+                        (lispobj *)pointer));
 }
 
 /* Is there any possibility that pointer is a valid Lisp object
@@ -3001,8 +2991,28 @@ free_oldspace(void)
               && (page_table[last_page].bytes_used != 0)
               && (page_table[last_page].gen == from_space));
 
-       /* Zero pages from first_page to (last_page-1). */
-       memset(page_address(first_page), 0, PAGE_BYTES*(last_page-first_page));
+       /* Zero pages from first_page to (last_page-1).
+        *
+        * FIXME: Why not use os_zero(..) function instead of
+        * hand-coding this again? (Check other gencgc_unmap_zero
+        * stuff too. */
+       if (gencgc_unmap_zero) {
+           void *page_start, *addr;
+
+           page_start = (void *)page_address(first_page);
+
+           os_invalidate(page_start, PAGE_BYTES*(last_page-first_page));
+           addr = os_validate(page_start, PAGE_BYTES*(last_page-first_page));
+           if (addr == NULL || addr != page_start) {
+               lose("free_oldspace: page moved, 0x%08x ==> 0x%08x",page_start,
+                    addr);
+           }
+       } else {
+           int *page_start;
+
+           page_start = (int *)page_address(first_page);
+           memset(page_start, 0,PAGE_BYTES*(last_page-first_page));
+       }
 
        first_page = last_page;
 
@@ -3501,7 +3511,7 @@ garbage_collect_generation(int generation, int raise)
        }
     }
 
-#if QSHOW
+#ifdef QSHOW
     if (gencgc_verbose > 1) {
        int num_dont_move_pages = count_dont_move_pages();
        fprintf(stderr,
@@ -4048,29 +4058,6 @@ alloc(int nbytes)
     new_obj = gc_alloc_with_region(nbytes,0,region,0);
     return (new_obj);
 }
-
-\f
-/* Find the code object for the given pc, or return NULL on failure.
- *
- * FIXME: PC shouldn't be lispobj*, should it? Maybe void*? */
-lispobj *
-component_ptr_from_pc(lispobj *pc)
-{
-    lispobj *object = NULL;
-
-    if ( (object = search_read_only_space(pc)) )
-       ;
-    else if ( (object = search_static_space(pc)) )
-       ;
-    else
-       object = search_dynamic_space(pc);
-
-    if (object) /* if we found something */
-       if (widetag_of(*object) == CODE_HEADER_WIDETAG) /* if it's a code object */
-           return(object);
-
-    return (NULL);
-}
 \f
 /*
  * shared support for the OS-dependent signal handlers which
@@ -4094,7 +4081,7 @@ gencgc_handle_wp_violation(void* fault_addr)
 {
     int  page_index = find_page_index(fault_addr);
 
-#if defined QSHOW_SIGNALS
+#ifdef QSHOW_SIGNALS
     FSHOW((stderr, "heap WP violation? fault_addr=%x, page_index=%d\n",
           fault_addr, page_index));
 #endif