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

  1. #include "debugger.h"
  2. #include "fail.h"
  3. #include "freelist.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.  
  12. value *c_roots_head;
  13.  
  14. /* Allocate more memory from malloc for the heap.
  15.    Return a block of at least the requested size (in words).
  16.    Return NULL when out of memory.
  17. */
  18. static char *expand_heap (request)
  19.      mlsize_t request;
  20. {
  21.   char *mem;
  22.   char *new_page_table;
  23.   asize_t new_page_table_size;
  24.   asize_t malloc_request;
  25.   asize_t i, more_pages;
  26.  
  27.   malloc_request = round_heap_chunk_size (Bhsize_wosize (request));
  28.   gc_message ("Growing heap to %ldk\n",
  29.           (stat_heap_size + malloc_request) / 1024);
  30.   mem = aligned_malloc (malloc_request + sizeof (heap_chunk_head),
  31.                         sizeof (heap_chunk_head));
  32.   if (mem == NULL){
  33.     gc_message ("No room for growing heap\n", 0);
  34.     return NULL;
  35.   }
  36.   mem += sizeof (heap_chunk_head);
  37.   (((heap_chunk_head *) mem) [-1]).size = malloc_request;
  38.   Assert (Wosize_bhsize (malloc_request) >= request);
  39.   Hd_hp (mem) = Make_header (Wosize_bhsize (malloc_request), 0, Blue);
  40.  
  41. #ifndef SIXTEEN
  42.   if (mem < heap_start){
  43.     more_pages = -Page (mem);
  44.   }else if (Page (mem + malloc_request) > page_table_size){
  45.     Assert (mem >= heap_end);
  46.     more_pages = Page (mem + malloc_request) - page_table_size;
  47.   }else{
  48.     more_pages = 0;
  49.   }
  50.  
  51.   if (more_pages != 0){
  52.     new_page_table_size = page_table_size + more_pages;
  53.     new_page_table = (char *) malloc (new_page_table_size);
  54.     if (new_page_table == NULL){
  55.       gc_message ("No room for growing page table\n", 0);
  56.       free (mem);
  57.       return NULL;
  58.     }
  59.   }
  60.  
  61.   if (mem < heap_start){
  62.     Assert (more_pages != 0);
  63.     for (i = 0; i < more_pages; i++){
  64.       new_page_table [i] = Not_in_heap;
  65.     }
  66.     bcopy (page_table, new_page_table + more_pages, page_table_size);
  67.     (((heap_chunk_head *) mem) [-1]).next = heap_start;
  68.     heap_start = mem;
  69.   }else{
  70.     char **last;
  71.     char *cur;
  72.  
  73.     if (mem >= heap_end) heap_end = mem + malloc_request;
  74.     if (more_pages != 0){
  75.       for (i = page_table_size; i < new_page_table_size; i++){
  76.         new_page_table [i] = Not_in_heap;
  77.       }
  78.       bcopy (page_table, new_page_table, page_table_size);
  79.     }
  80.     last = &heap_start;
  81.     cur = *last;
  82.     while (cur != NULL && cur < mem){
  83.       last = &((((heap_chunk_head *) cur) [-1]).next);
  84.       cur = *last;
  85.     }
  86.     (((heap_chunk_head *) mem) [-1]).next = cur;
  87.     *last = mem;
  88.   }
  89.  
  90.   if (more_pages != 0){
  91.     free (page_table);
  92.     page_table = new_page_table;
  93.     page_table_size = new_page_table_size;
  94.   }
  95. #else                           /* Simplified version for the 8086 */
  96.   {
  97.     char **last;
  98.     char *cur;
  99.  
  100.     last = &heap_start;
  101.     cur = *last;
  102.     while (cur != NULL && (char huge *) cur < (char huge *) mem){
  103.       last = &((((heap_chunk_head *) cur) [-1]).next);
  104.       cur = *last;
  105.     }
  106.     (((heap_chunk_head *) mem) [-1]).next = cur;
  107.     *last = mem;
  108.   }
  109. #endif
  110.  
  111.   for (i = Page (mem); i < Page (mem + malloc_request); i++){
  112.     page_table [i] = In_heap;
  113.   }
  114.   stat_heap_size += malloc_request;
  115.   return Bp_hp (mem);
  116. }
  117.  
  118. value alloc_shr (wosize, tag)
  119.      mlsize_t wosize;
  120.      tag_t tag;
  121. {
  122.   char *hp, *new_block;
  123.  
  124.   hp = fl_allocate (wosize);
  125.   if (hp == NULL){
  126.     new_block = expand_heap (wosize);
  127.     if (new_block == NULL) raise_out_of_memory ();
  128.     fl_add_block (new_block);
  129.     hp = fl_allocate (wosize);
  130.     if (hp == NULL) fatal_error ("alloc_shr: expand heap failed\n");
  131.   }
  132.  
  133.   Assert (Is_in_heap (Val_hp (hp)));
  134.  
  135.   if (gc_phase == Phase_mark || (addr)hp >= (addr)gc_sweep_hp){
  136.     Hd_hp (hp) = Make_header (wosize, tag, Black);
  137.   }else{
  138.     Hd_hp (hp) = Make_header (wosize, tag, White);
  139.   }
  140.   allocated_words += Whsize_wosize (wosize);
  141.   if (allocated_words > Wsize_bsize (minor_heap_size)) force_minor_gc ();
  142.   return Val_hp (hp);
  143. }
  144.  
  145. /* Use this function to tell the major GC to speed up when you use
  146.    finalized objects to automatically deallocate extra-heap objects.
  147.    The GC will do at least one cycle every [max] allocated words;
  148.    [mem] is the number of words allocated this time.
  149.    Note that only [mem/max] is relevant.  You can use numbers of bytes
  150.    (or kilobytes, ...) instead of words.  You can change units between
  151.    calls to [adjust_collector_speed].
  152. */
  153. void adjust_gc_speed (mem, max)
  154.      mlsize_t mem, max;
  155. {
  156.   if (max == 0) max = 1;
  157.   if (mem > max) mem = max;
  158.   extra_heap_memory += ((float) mem / max) * stat_heap_size;
  159.   if (extra_heap_memory > stat_heap_size){
  160.     extra_heap_memory = stat_heap_size;
  161.   }
  162.   if (extra_heap_memory > Wsize_bsize (minor_heap_size) / 2) force_minor_gc ();
  163. }
  164.  
  165. /* You must use [initialize] to store the initial value in a field of
  166.    a shared block, unless you are sure the value is not a young block.
  167.    A block value [v] is a shared block if and only if [Is_in_heap (v)]
  168.    is true.
  169. */
  170. /* [initialize] never calls the GC, so you may call it while an object is
  171.    unfinished (i.e. just after a call to [alloc_shr].) */
  172. void initialize (fp, val)
  173.      value *fp;
  174.      value val;
  175. {
  176.   *fp = val;
  177.   Assert (Is_in_heap (fp));
  178.   if (Is_block (val) && Is_young (val)){
  179.     *ref_table_ptr++ = fp;
  180.     if (ref_table_ptr >= ref_table_limit){
  181.       realloc_ref_table ();
  182.     }
  183.   }
  184. }
  185.  
  186. /* You must use [modify] to change a field of an existing shared block,
  187.    unless you are sure the value being overwritten is not a shared block and
  188.    the value being written is not a young block. */
  189. /* [modify] never calls the GC. */
  190. void modify (fp, val)
  191.      value *fp;
  192.      value val;
  193. {
  194.   Modify (fp, val);
  195. }
  196.  
  197. char *stat_alloc (sz)
  198.      asize_t sz;
  199. {
  200.   char *result = (char *) malloc (sz);
  201.  
  202.   if (result == NULL) raise_out_of_memory ();
  203.   return result;
  204. }
  205.  
  206. void stat_free (blk)
  207.      char * blk;
  208. {
  209.   free (blk);
  210. }
  211.  
  212. char *stat_resize (blk, sz)
  213.      char *blk;
  214.      asize_t sz;
  215. {
  216.   char *result = (char *) realloc (blk, sz);
  217.  
  218.   if (result == NULL) raise_out_of_memory ();
  219.   return result;
  220. }
  221.  
  222. void init_c_roots ()
  223. {
  224.   c_roots_head = NULL;
  225. }
  226.