1.0.32.33: GENCGC tuning parameters
[sbcl.git] / src / runtime / gencgc.c
index 3353425..5bd67c8 100644 (file)
@@ -69,9 +69,7 @@ page_index_t  gc_find_freeish_pages(long *restart_page_ptr, long nbytes,
  * scratch space by the collector, and should never get collected.
  */
 enum {
-    HIGHEST_NORMAL_GENERATION = 5,
-    PSEUDO_STATIC_GENERATION,
-    SCRATCH_GENERATION,
+    SCRATCH_GENERATION = PSEUDO_STATIC_GENERATION+1,
     NUM_GENERATIONS
 };
 
@@ -89,7 +87,7 @@ long 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. */
-#ifdef QSHOW
+#if QSHOW
 boolean gencgc_verbose = 1;
 #else
 boolean gencgc_verbose = 0;
@@ -257,7 +255,12 @@ size_t void_diff(void *x, void *y)
     return (pointer_sized_uint_t)x - (pointer_sized_uint_t)y;
 }
 
-/* a structure to hold the state of a generation */
+/* a structure to hold the state of a generation
+ *
+ * CAUTION: If you modify this, make sure to touch up the alien
+ * definition in src/code/gc.lisp accordingly. ...or better yes,
+ * deal with the FIXME there...
+ */
 struct generation {
 
     /* the first page that gc_alloc() checks on its next call */
@@ -287,9 +290,9 @@ struct generation {
     /* the number of GCs since the last raise */
     int num_gc;
 
-    /* the average age after which a GC will raise objects to the
+    /* the number of GCs to run on the generations before raising objects to the
      * next generation */
-    int trigger_age;
+    int number_of_gcs_before_promotion;
 
     /* the cumulative sum of the bytes allocated to this generation. It is
      * cleared after a GC on this generations, and update before new
@@ -301,7 +304,7 @@ struct generation {
     /* a minimum average memory age before a GC will occur helps
      * prevent a GC when a large number of new live objects have been
      * added, in which case a GC could be a waste of time */
-    double min_av_mem_age;
+    double minimum_age_before_gc;
 
     /* A linked list of lutex structures in this generation, used for
      * implementing lutex finalization. */
@@ -384,7 +387,7 @@ count_generation_pages(generation_index_t generation)
     return count;
 }
 
-#ifdef QSHOW
+#if QSHOW
 static long
 count_dont_move_pages(void)
 {
@@ -416,8 +419,8 @@ count_generation_bytes_allocated (generation_index_t gen)
 }
 
 /* Return the average age of the memory in a generation. */
-static double
-gen_av_mem_age(generation_index_t gen)
+extern double
+generation_average_age(generation_index_t gen)
 {
     if (generations[gen].bytes_allocated == 0)
         return 0.0;
@@ -429,10 +432,10 @@ gen_av_mem_age(generation_index_t gen)
 
 /* The verbose argument controls how much to print: 0 for normal
  * level of detail; 1 for debugging. */
-static void
-print_generation_stats(int verbose) /* FIXME: should take FILE argument */
+extern void
+print_generation_stats() /* FIXME: should take FILE argument, or construct a string */
 {
-    generation_index_t i, gens;
+    generation_index_t i;
 
 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
 #define FPU_STATE_SIZE 27
@@ -446,17 +449,11 @@ print_generation_stats(int verbose) /* FIXME: should take FILE argument */
      * so they need to be saved and reset for C. */
     fpu_save(fpu_state);
 
-    /* highest generation to print */
-    if (verbose)
-        gens = SCRATCH_GENERATION;
-    else
-        gens = PSEUDO_STATIC_GENERATION;
-
     /* Print the heap stats. */
     fprintf(stderr,
             " Gen StaPg UbSta LaSta LUbSt Boxed Unboxed LB   LUB  !move  Alloc  Waste   Trig    WP  GCs Mem-age\n");
 
-    for (i = 0; i < gens; i++) {
+    for (i = 0; i < SCRATCH_GENERATION; i++) {
         page_index_t j;
         long boxed_cnt = 0;
         long unboxed_cnt = 0;
@@ -506,7 +503,7 @@ print_generation_stats(int verbose) /* FIXME: should take FILE argument */
                 generations[i].gc_trigger,
                 count_write_protect_generation_pages(i),
                 generations[i].num_gc,
-                gen_av_mem_age(i));
+                generation_average_age(i));
     }
     fprintf(stderr,"   Total bytes allocated    = %lu\n", bytes_allocated);
     fprintf(stderr,"   Dynamic-space-size bytes = %u\n", dynamic_space_size);
@@ -1168,7 +1165,7 @@ gc_heap_exhausted_error_or_lose (long available, long requested)
         /* If we are in GC, or totally out of memory there is no way
          * to sanely transfer control to the lisp-side of things.
          */
-        print_generation_stats(1);
+        print_generation_stats();
         fprintf(stderr, "GC control variables:\n");
         fprintf(stderr, "          *GC-INHIBIT* = %s\n          *GC-PENDING* = %s\n",
                 SymbolValue(GC_INHIBIT,thread)==NIL ? "false" : "true",
@@ -1684,7 +1681,7 @@ sniff_code_object(struct code *code, unsigned long displacement)
         unsigned d2 = *((unsigned char *)p - 2);
         unsigned d3 = *((unsigned char *)p - 3);
         unsigned d4 = *((unsigned char *)p - 4);
-#ifdef QSHOW
+#if QSHOW
         unsigned d5 = *((unsigned char *)p - 5);
         unsigned d6 = *((unsigned char *)p - 6);
 #endif
@@ -4096,7 +4093,7 @@ garbage_collect_generation(generation_index_t generation, int raise)
     }
 #endif
 
-#ifdef QSHOW
+#if QSHOW
     if (gencgc_verbose > 1) {
         long num_dont_move_pages = count_dont_move_pages();
         fprintf(stderr,
@@ -4352,7 +4349,7 @@ collect_garbage(generation_index_t last_gen)
     }
 
     if (gencgc_verbose > 1)
-        print_generation_stats(0);
+        print_generation_stats();
 
     do {
         /* Collect the generation. */
@@ -4363,7 +4360,7 @@ collect_garbage(generation_index_t last_gen)
         } else {
             raise =
                 (gen < last_gen)
-                || (generations[gen].num_gc >= generations[gen].trigger_age);
+                || (generations[gen].num_gc >= generations[gen].number_of_gcs_before_promotion);
         }
 
         if (gencgc_verbose > 1) {
@@ -4390,7 +4387,7 @@ collect_garbage(generation_index_t last_gen)
 
         if (gencgc_verbose > 1) {
             FSHOW((stderr, "GC of generation %d finished:\n", gen));
-            print_generation_stats(0);
+            print_generation_stats();
         }
 
         gen++;
@@ -4400,8 +4397,8 @@ collect_garbage(generation_index_t last_gen)
                      && raise
                      && (generations[gen].bytes_allocated
                          > generations[gen].gc_trigger)
-                     && (gen_av_mem_age(gen)
-                         > generations[gen].min_av_mem_age))));
+                     && (generation_average_age(gen)
+                         > generations[gen].minimum_age_before_gc))));
 
     /* Now if gen-1 was raised all generations before gen are empty.
      * If it wasn't raised then all generations before gen-1 are empty.
@@ -4536,7 +4533,7 @@ gc_free_heap(void)
     }
 
     if (gencgc_verbose > 1)
-        print_generation_stats(0);
+        print_generation_stats();
 
     /* Initialize gc_alloc(). */
     gc_alloc_generation = 0;
@@ -4605,8 +4602,8 @@ gc_init(void)
         generations[i].cum_sum_bytes_allocated = 0;
         /* the tune-able parameters */
         generations[i].bytes_consed_between_gc = 2000000;
-        generations[i].trigger_age = 1;
-        generations[i].min_av_mem_age = 0.75;
+        generations[i].number_of_gcs_before_promotion = 1;
+        generations[i].minimum_age_before_gc = 0.75;
         generations[i].lutexes = NULL;
     }
 
@@ -4632,7 +4629,6 @@ gencgc_pickup_dynamic(void)
     generation_index_t gen = PSEUDO_STATIC_GENERATION;
     do {
         lispobj *first,*ptr= (lispobj *)page_address(page);
-        page_table[page].allocated = BOXED_PAGE_FLAG;
         page_table[page].gen = gen;
         page_table[page].bytes_used = PAGE_BYTES;
         page_table[page].large_object = 0;
@@ -4642,8 +4638,10 @@ gencgc_pickup_dynamic(void)
         page_table[page].need_to_zero = 1;
 
         if (!gencgc_partial_pickup) {
+            page_table[page].allocated = BOXED_PAGE_FLAG;
             first=gc_search_space(prev,(ptr+2)-prev,ptr);
-            if(ptr == first)  prev=ptr;
+            if(ptr == first)
+                prev=ptr;
             page_table[page].region_start_offset =
                 page_address(page) - (void *)prev;
         }
@@ -4726,10 +4724,14 @@ general_alloc_internal(long nbytes, int page_type_flag, struct alloc_region *reg
             if (SymbolValue(GC_INHIBIT,thread) == NIL) {
                 set_pseudo_atomic_interrupted(thread);
 #ifdef LISP_FEATURE_PPC
-                /* PPC calls alloc() from a trap, look up the most
-                 * recent one and frob that. */
-                maybe_save_gc_mask_and_block_deferrables
-                    (get_interrupt_context_for_thread(thread));
+                /* PPC calls alloc() from a trap or from pa_alloc(),
+                 * look up the most context if it's from a trap. */
+                {
+                    os_context_t *context =
+                        thread->interrupt_data->allocation_trap_context;
+                    maybe_save_gc_mask_and_block_deferrables
+                        (context ? os_context_sigmask_addr(context) : NULL);
+                }
 #else
                 maybe_save_gc_mask_and_block_deferrables(NULL);
 #endif
@@ -4808,7 +4810,7 @@ gencgc_handle_wp_violation(void* fault_addr)
 {
     page_index_t page_index = find_page_index(fault_addr);
 
-#ifdef QSHOW_SIGNALS
+#if QSHOW_SIGNALS
     FSHOW((stderr, "heap WP violation? fault_addr=%x, page_index=%d\n",
            fault_addr, page_index));
 #endif