home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / !runtime / minor_gc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  5.0 KB  |  163 lines  |  [TEXT/R*ch]

  1. #include "config.h"
  2. #include "debugger.h"
  3. #include "fail.h"
  4. #include "gc.h"
  5. #include "gc_ctrl.h"
  6. #include "major_gc.h"
  7. #include "memory.h"
  8. #include "minor_gc.h"
  9. #include "misc.h"
  10. #include "mlvalues.h"
  11. #include "roots.h"
  12.  
  13. #include "runtime.h"
  14.  
  15. asize_t minor_heap_size;
  16. char *young_start = NULL, *young_end, *young_ptr = NULL;
  17. static value **ref_table = NULL, **ref_table_end, **ref_table_threshold;
  18. value **ref_table_ptr = NULL, **ref_table_limit;
  19. static asize_t ref_table_size, ref_table_reserve;
  20.  
  21. void set_minor_heap_size (size)
  22.     asize_t size;
  23. {
  24.   char *new_heap;
  25.   value **new_table;
  26.  
  27.   Assert (size >= Minor_heap_min);
  28.   Assert (size <= Minor_heap_max);
  29.   Assert (size % sizeof (value) == 0);
  30.   if (young_ptr != young_start) minor_collection ();
  31.                                            Assert (young_ptr == young_start);
  32.   new_heap = (char *) stat_alloc (size);
  33.   if (young_start != NULL){
  34.     stat_free ((char *) young_start);
  35.   }
  36.   young_start = new_heap;
  37.   young_end = new_heap + size;
  38.   young_ptr = young_start;
  39.   minor_heap_size = size;
  40.  
  41.   ref_table_size = minor_heap_size / sizeof (value) / 8;
  42.   ref_table_reserve = 256;
  43.   new_table = (value **) stat_alloc ((ref_table_size + ref_table_reserve)
  44.                      * sizeof (value *));
  45.   if (ref_table != NULL) stat_free ((char *) ref_table);
  46.   ref_table = new_table;
  47.   ref_table_ptr = ref_table;
  48.   ref_table_threshold = ref_table + ref_table_size;
  49.   ref_table_limit = ref_table_threshold;
  50.   ref_table_end = ref_table + ref_table_size + ref_table_reserve;
  51. }
  52.  
  53. static void oldify (p, v)
  54.      value *p;
  55.      value v;
  56. {
  57.   value result;
  58.   mlsize_t i;
  59.  
  60.  tail_call:
  61.   if (Is_block (v) && Is_young (v)){
  62.     Assert (Hp_val (v) < young_ptr);
  63.     if (Is_blue_val (v)){    /* Already forwarded ? */
  64.       *p = Field (v, 0);     /* Then the forward pointer is the first field. */
  65.     }else if (Tag_val (v) >= No_scan_tag){
  66.       result = alloc_shr (Wosize_val (v), Tag_val (v));
  67.       bcopy (Bp_val (v), Bp_val (result), Bosize_val (v));
  68.       Hd_val (v) = Bluehd_hd (Hd_val (v));    /* Put the forward flag. */
  69.       Field (v, 0) = result;                  /* And the forward pointer. */
  70.       *p = result;
  71.     }else{
  72.       /* We can do recursive calls before all the fields are filled, because
  73.          we will not be calling the major GC. */
  74.       value field0 = Field (v, 0);
  75.       mlsize_t sz = Wosize_val (v);
  76.  
  77.       result = alloc_shr (sz, Tag_val (v));
  78.       *p = result;
  79.       Hd_val (v) = Bluehd_hd (Hd_val (v));    /* Put the forward flag. */
  80.       Field (v, 0) = result;                  /* And the forward pointer. */
  81.       if (sz == 1){
  82.         p = &Field (result, 0);
  83.         v = field0;
  84.         goto tail_call;
  85.       }else{
  86.         oldify (&Field (result, 0), field0);
  87.         for (i = 1; i < sz - 1; i++){
  88.           oldify (&Field (result, i), Field (v, i));
  89.         }
  90.         p = &Field (result, i);
  91.         v = Field (v, i);
  92.         goto tail_call;
  93.       }
  94.     }
  95.   }else{
  96.     *p = v;
  97.   }
  98. }
  99.  
  100. void minor_collection ()
  101. {
  102.   value **r;
  103.   struct longjmp_buffer raise_buf;
  104.   struct longjmp_buffer *old_external_raise;
  105.   long prev_alloc_words = allocated_words;
  106.  
  107.   if (setjmp(raise_buf.buf)) {
  108.     fatal_error ("Fatal error: out of memory.\n");
  109.   }
  110.   old_external_raise = external_raise;
  111.   external_raise = &raise_buf;
  112.  
  113.   beg_gc_time();
  114.  
  115.   gc_message ("<", 0);
  116.   local_roots (oldify);
  117.   for (r = ref_table; r < ref_table_ptr; r++) oldify (*r, **r);
  118.   stat_minor_words += Wsize_bsize (young_ptr - young_start);
  119.   young_ptr = young_start;
  120.   ref_table_ptr = ref_table;
  121.   ref_table_limit = ref_table_threshold;
  122.   gc_message (">", 0);
  123.  
  124.   external_raise = old_external_raise;
  125.  
  126.   stat_promoted_words += allocated_words - prev_alloc_words;
  127.   ++ stat_minor_collections;
  128.   major_collection_slice ();
  129.  
  130.   end_gc_time();
  131.  
  132. }
  133.  
  134. void realloc_ref_table ()
  135. {                                 Assert (ref_table_ptr == ref_table_limit);
  136.                                   Assert (ref_table_limit <= ref_table_end);
  137.                             Assert (ref_table_limit >= ref_table_threshold);
  138.  
  139.   if (ref_table_limit == ref_table_threshold){
  140.     gc_message ("ref_table threshold crossed\n", 0);
  141.     ref_table_limit = ref_table_end;
  142.     force_minor_gc ();
  143.   }else{                                       /* This will never happen. */
  144.     asize_t sz;
  145.     asize_t cur_ptr = ref_table_ptr - ref_table;
  146.                                                   Assert (force_minor_flag);
  147.                                                    Assert (something_to_do);
  148.     ref_table_reserve += 1024;
  149.     sz = (ref_table_size + ref_table_reserve) * sizeof (value *);
  150.     gc_message ("Growing ref_table to %ldk\n", (long) sz / 1024);
  151. #ifdef MAX_MALLOC_SIZE
  152.     if (sz > MAX_MALLOC_SIZE) ref_table = NULL;
  153.     else
  154. #endif
  155.     ref_table = (value **) realloc ((char *) ref_table, sz);
  156.     if (ref_table == NULL) fatal_error ("Fatal error: ref_table overflow\n");
  157.     ref_table_end = ref_table + ref_table_size + ref_table_reserve;
  158.     ref_table_threshold = ref_table + ref_table_size;
  159.     ref_table_ptr = ref_table + cur_ptr;
  160.     ref_table_limit = ref_table_end;
  161.   }
  162. }
  163.