PageRenderTime 290ms CodeModel.GetById 81ms app.highlight 129ms RepoModel.GetById 72ms app.codeStats 0ms

/src/runtime/major_gc.c

https://github.com/bluegnu/mosml
C | 771 lines | 675 code | 45 blank | 51 comment | 384 complexity | 55d3c6771b0ae74ba1fe9bf6257df524 MD5 | raw file
  1#include <stdlib.h>
  2#include <stdint.h>
  3#include "config.h"
  4#include "debugger.h"
  5#include "fail.h"
  6#include "freelist.h"
  7#include "gc.h"
  8#include "gc_ctrl.h"
  9#include "globals.h"
 10#include "major_gc.h"
 11#include "misc.h"
 12#include "mlvalues.h"
 13#include "roots.h"
 14
 15#ifdef macintosh
 16#include <Memory.h>
 17#endif
 18
 19#include "runtime.h"
 20
 21#ifdef ANSI
 22#include <limits.h>
 23#else
 24#ifdef SIXTYFOUR
 25#define LONG_MAX 0x7FFFFFFFFFFFFFFF
 26#else
 27#define LONG_MAX 0x7FFFFFFF
 28#endif
 29#endif
 30
 31int percent_free;
 32long major_heap_increment;
 33char *heap_start, *heap_end;
 34char *page_table;
 35asize_t page_table_size;
 36char *gc_sweep_hp;
 37int gc_phase;
 38
 39typedef struct {
 40  intptr_t low, high;
 41} p_table_entry;
 42
 43static p_table_entry *p_table;
 44static size_t p_table_total_size;
 45static size_t p_table_current_size;
 46
 47void p_table_init(size_t initial) {
 48  p_table = malloc(initial*sizeof(p_table_entry));
 49  if(p_table == NULL)
 50      fatal_error ("No room for allocating page table\n");
 51  p_table_total_size = initial;
 52  p_table_current_size = 0;
 53}
 54
 55#define RawPage(p) (((intptr_t) (p)) >> Page_log)
 56
 57char p_table_in_heap_simple(addr a) {
 58  int i;
 59  intptr_t p = RawPage(a);
 60  for(i = 0; i < p_table_current_size; i++) {
 61    //printf("p: %u low: %u high: %u\n", p, p_table[i].low, p_table[i].high);
 62    if(p_table[i].low <= p && p < p_table[i].high) {
 63      return In_heap;
 64    }
 65  }
 66  return Not_in_heap;
 67}
 68
 69char p_table_in_heap_16(addr a) {
 70  intptr_t p = RawPage(a);
 71  int i = 0;
 72  while(i + 15 < p_table_current_size) {
 73    if(   (p_table[i].low <= p && p < p_table[i].high)
 74       || (p_table[i + 1].low <= p && p < p_table[i + 1].high)
 75       || (p_table[i + 2].low <= p && p < p_table[i + 2].high)
 76       || (p_table[i + 3].low <= p && p < p_table[i + 3].high)
 77       || (p_table[i + 4].low <= p && p < p_table[i + 4].high)
 78       || (p_table[i + 5].low <= p && p < p_table[i + 5].high)
 79       || (p_table[i + 6].low <= p && p < p_table[i + 6].high)
 80       || (p_table[i + 7].low <= p && p < p_table[i + 7].high)
 81       || (p_table[i + 8].low <= p && p < p_table[i + 8].high)
 82       || (p_table[i + 9].low <= p && p < p_table[i + 9].high)
 83       || (p_table[i + 10].low <= p && p < p_table[i + 10].high)
 84       || (p_table[i + 11].low <= p && p < p_table[i + 11].high)
 85       || (p_table[i + 12].low <= p && p < p_table[i + 12].high)
 86       || (p_table[i + 13].low <= p && p < p_table[i + 13].high)
 87       || (p_table[i + 14].low <= p && p < p_table[i + 14].high)
 88       || (p_table[i + 15].low <= p && p < p_table[i + 15].high)
 89       ) return In_heap;
 90    i += 16;
 91  }
 92  switch(p_table_current_size - i) {
 93  case 15:
 94    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
 95    i++;
 96  case 14:
 97    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
 98    i++;
 99  case 13:
100    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
101    i++;
102  case 12:
103    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
104    i++;
105  case 11:
106    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
107    i++;
108  case 10:
109    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
110    i++;
111  case 9:
112    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
113    i++;
114  case 8:
115    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
116    i++;
117  case 7:
118    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
119    i++;
120  case 6:
121    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
122    i++;
123  case 5:
124    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
125    i++;
126  case 4:
127    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
128    i++;
129  case 3:
130    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
131    i++;
132  case 2:
133    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
134    i++;
135  case 1:
136    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
137    i++;
138  default: return Not_in_heap;
139  }
140}
141
142char p_table_in_heap(addr a) {
143  intptr_t p = RawPage(a);
144  int i = 0;
145  while(i + 63 < p_table_current_size) {
146    if(   (p_table[i].low <= p && p < p_table[i].high)
147       || (p_table[i + 1].low <= p && p < p_table[i + 1].high)
148       || (p_table[i + 2].low <= p && p < p_table[i + 2].high)
149       || (p_table[i + 3].low <= p && p < p_table[i + 3].high)
150       || (p_table[i + 4].low <= p && p < p_table[i + 4].high)
151       || (p_table[i + 5].low <= p && p < p_table[i + 5].high)
152       || (p_table[i + 6].low <= p && p < p_table[i + 6].high)
153       || (p_table[i + 7].low <= p && p < p_table[i + 7].high)
154       || (p_table[i + 8].low <= p && p < p_table[i + 8].high)
155       || (p_table[i + 9].low <= p && p < p_table[i + 9].high)
156       || (p_table[i + 10].low <= p && p < p_table[i + 10].high)
157       || (p_table[i + 11].low <= p && p < p_table[i + 11].high)
158       || (p_table[i + 12].low <= p && p < p_table[i + 12].high)
159       || (p_table[i + 13].low <= p && p < p_table[i + 13].high)
160       || (p_table[i + 14].low <= p && p < p_table[i + 14].high)
161       || (p_table[i + 15].low <= p && p < p_table[i + 15].high)
162       || (p_table[i + 16].low <= p && p < p_table[i + 16].high)
163       || (p_table[i + 17].low <= p && p < p_table[i + 17].high)
164       || (p_table[i + 18].low <= p && p < p_table[i + 18].high)
165       || (p_table[i + 19].low <= p && p < p_table[i + 19].high)
166       || (p_table[i + 20].low <= p && p < p_table[i + 20].high)
167       || (p_table[i + 21].low <= p && p < p_table[i + 21].high)
168       || (p_table[i + 22].low <= p && p < p_table[i + 22].high)
169       || (p_table[i + 23].low <= p && p < p_table[i + 23].high)
170       || (p_table[i + 24].low <= p && p < p_table[i + 24].high)
171       || (p_table[i + 25].low <= p && p < p_table[i + 25].high)
172       || (p_table[i + 26].low <= p && p < p_table[i + 26].high)
173       || (p_table[i + 27].low <= p && p < p_table[i + 27].high)
174       || (p_table[i + 28].low <= p && p < p_table[i + 28].high)
175       || (p_table[i + 29].low <= p && p < p_table[i + 29].high)
176       || (p_table[i + 30].low <= p && p < p_table[i + 30].high)
177       || (p_table[i + 31].low <= p && p < p_table[i + 31].high)
178       || (p_table[i + 32].low <= p && p < p_table[i + 32].high)
179       || (p_table[i + 33].low <= p && p < p_table[i + 33].high)
180       || (p_table[i + 34].low <= p && p < p_table[i + 34].high)
181       || (p_table[i + 35].low <= p && p < p_table[i + 35].high)
182       || (p_table[i + 36].low <= p && p < p_table[i + 36].high)
183       || (p_table[i + 37].low <= p && p < p_table[i + 37].high)
184       || (p_table[i + 38].low <= p && p < p_table[i + 38].high)
185       || (p_table[i + 39].low <= p && p < p_table[i + 39].high)
186       || (p_table[i + 40].low <= p && p < p_table[i + 40].high)
187       || (p_table[i + 41].low <= p && p < p_table[i + 41].high)
188       || (p_table[i + 42].low <= p && p < p_table[i + 42].high)
189       || (p_table[i + 43].low <= p && p < p_table[i + 43].high)
190       || (p_table[i + 44].low <= p && p < p_table[i + 44].high)
191       || (p_table[i + 45].low <= p && p < p_table[i + 45].high)
192       || (p_table[i + 46].low <= p && p < p_table[i + 46].high)
193       || (p_table[i + 47].low <= p && p < p_table[i + 47].high)
194       || (p_table[i + 48].low <= p && p < p_table[i + 48].high)
195       || (p_table[i + 49].low <= p && p < p_table[i + 49].high)
196       || (p_table[i + 50].low <= p && p < p_table[i + 50].high)
197       || (p_table[i + 51].low <= p && p < p_table[i + 51].high)
198       || (p_table[i + 52].low <= p && p < p_table[i + 52].high)
199       || (p_table[i + 53].low <= p && p < p_table[i + 53].high)
200       || (p_table[i + 54].low <= p && p < p_table[i + 54].high)
201       || (p_table[i + 55].low <= p && p < p_table[i + 55].high)
202       || (p_table[i + 56].low <= p && p < p_table[i + 56].high)
203       || (p_table[i + 57].low <= p && p < p_table[i + 57].high)
204       || (p_table[i + 58].low <= p && p < p_table[i + 58].high)
205       || (p_table[i + 59].low <= p && p < p_table[i + 59].high)
206       || (p_table[i + 60].low <= p && p < p_table[i + 60].high)
207       || (p_table[i + 61].low <= p && p < p_table[i + 61].high)
208       || (p_table[i + 62].low <= p && p < p_table[i + 62].high)
209       || (p_table[i + 63].low <= p && p < p_table[i + 63].high)
210       ) return In_heap;
211    i += 64;
212  }
213  switch(p_table_current_size - i) {
214  case 63:
215    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
216    i++;
217  case 62:
218    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
219    i++;
220  case 61:
221    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
222    i++;
223  case 60:
224    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
225    i++;
226  case 59:
227    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
228    i++;
229  case 58:
230    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
231    i++;
232  case 57:
233    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
234    i++;
235  case 56:
236    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
237    i++;
238  case 55:
239    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
240    i++;
241  case 54:
242    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
243    i++;
244  case 53:
245    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
246    i++;
247  case 52:
248    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
249    i++;
250  case 51:
251    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
252    i++;
253  case 50:
254    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
255    i++;
256  case 49:
257    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
258    i++;
259  case 48:
260    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
261    i++;
262  case 47:
263    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
264    i++;
265  case 46:
266    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
267    i++;
268  case 45:
269    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
270    i++;
271  case 44:
272    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
273    i++;
274  case 43:
275    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
276    i++;
277  case 42:
278    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
279    i++;
280  case 41:
281    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
282    i++;
283  case 40:
284    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
285    i++;
286  case 39:
287    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
288    i++;
289  case 38:
290    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
291    i++;
292  case 37:
293    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
294    i++;
295  case 36:
296    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
297    i++;
298  case 35:
299    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
300    i++;
301  case 34:
302    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
303    i++;
304  case 33:
305    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
306    i++;
307  case 32:
308    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
309    i++;
310  case 31:
311    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
312    i++;
313  case 30:
314    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
315    i++;
316  case 29:
317    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
318    i++;
319  case 28:
320    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
321    i++;
322  case 27:
323    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
324    i++;
325  case 26:
326    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
327    i++;
328  case 25:
329    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
330    i++;
331  case 24:
332    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
333    i++;
334  case 23:
335    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
336    i++;
337  case 22:
338    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
339    i++;
340  case 21:
341    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
342    i++;
343  case 20:
344    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
345    i++;
346  case 19:
347    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
348    i++;
349  case 18:
350    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
351    i++;
352  case 17:
353    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
354    i++;
355  case 16:
356    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
357    i++;
358  case 15:
359    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
360    i++;
361  case 14:
362    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
363    i++;
364  case 13:
365    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
366    i++;
367  case 12:
368    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
369    i++;
370  case 11:
371    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
372    i++;
373  case 10:
374    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
375    i++;
376  case 9:
377    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
378    i++;
379  case 8:
380    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
381    i++;
382  case 7:
383    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
384    i++;
385  case 6:
386    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
387    i++;
388  case 5:
389    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
390    i++;
391  case 4:
392    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
393    i++;
394  case 3:
395    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
396    i++;
397  case 2:
398    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
399    i++;
400  case 1:
401    if(p_table[i].low <= p && p < p_table[i].high) return In_heap;
402    i++;
403  default: return Not_in_heap;
404  }
405}
406
407
408void p_table_update_size() {
409  p_table_total_size *= 2;
410  p_table = realloc(p_table, sizeof(p_table_entry)*p_table_total_size);
411  if(p_table == NULL)
412    fatal_error("No memory for page table");
413  gc_message ("Growing p_table to %ld\n", p_table_total_size);
414
415}
416
417void p_table_add_pages(addr start, addr end) {
418  intptr_t s, e;
419  if(p_table_current_size == p_table_total_size)
420    p_table_update_size();
421  p_table[p_table_current_size].low = RawPage(start);
422  p_table[p_table_current_size].high = RawPage(end);
423  p_table_current_size++;
424}
425
426
427
428/* The mark phase will register pointers to live arrays of weak
429   pointers in weak_arrays.  Then the weak phase traverses each weak
430   array and resets pointers to objects that will be deallocated by the
431   sweep phase: 
432*/
433
434static value *weak_arrays;
435value *weak_arrays_cur, *weak_arrays_end;
436static asize_t weak_arrays_size;
437
438static value *gray_vals;
439value *gray_vals_cur, *gray_vals_end;
440static asize_t gray_vals_size;
441static int heap_is_pure;   /* The heap is pure if the only gray objects
442                              below [markhp] are also in [gray_vals]. */
443unsigned long allocated_words;
444unsigned long extra_heap_memory;
445extern char *fl_merge;  /* Defined in freelist.c. */
446
447static char *markhp, *chunk, *limit;
448
449static void realloc_gray_vals (void)
450{
451  value *new;
452
453  Assert (gray_vals_cur == gray_vals_end);
454  if (gray_vals_size < stat_heap_size / 128){
455    gc_message ("Growing gray_vals to %ldk\n",
456		(long) gray_vals_size * sizeof (value) / 512);
457    new = (value *) realloc ((char *) gray_vals,
458                             2 * gray_vals_size * sizeof (value));
459    if (new == NULL){
460      gc_message ("No room for growing gray_vals\n", 0);
461      gray_vals_cur = gray_vals;
462      heap_is_pure = 0;
463    }else{
464      gray_vals = new;
465      gray_vals_cur = gray_vals + gray_vals_size;
466      gray_vals_size *= 2;
467      gray_vals_end = gray_vals + gray_vals_size;
468    }
469  }else{
470    gray_vals_cur = gray_vals + gray_vals_size / 2;
471    heap_is_pure = 0;
472  }
473}
474
475static void realloc_weak_arrays (void)
476{
477  value *new;
478
479  Assert (weak_arrays_cur == weak_arrays_end);
480  gc_message ("Growing weak_arrays to %ld\n",
481              (long) weak_arrays_size * 2);
482  new = (value *) realloc ((char *) weak_arrays,
483                             2 * weak_arrays_size * sizeof (value));
484  if (new == NULL){
485    fatal_error ("Fatal error: cannot grow weak_arrays table.\n");
486  }else{
487    weak_arrays = new;
488    weak_arrays_cur = weak_arrays + weak_arrays_size;
489    weak_arrays_size *= 2;
490    weak_arrays_end = weak_arrays + weak_arrays_size;
491  }
492}
493
494void darken (value v)
495{
496  if (Is_block (v) && Is_in_heap (v) && Is_white_val (v)){
497    Hd_val (v) = Grayhd_hd (Hd_val (v));
498    *gray_vals_cur++ = v;
499    if (gray_vals_cur >= gray_vals_end) realloc_gray_vals ();
500  }
501}
502
503static void darken_root (value *p, value v)
504{
505  darken (v);
506}
507
508static void start_cycle (void)
509{
510  Assert (gray_vals_cur == gray_vals);
511  Assert (Is_white_val (global_data));
512  darken (global_data);
513  local_roots (darken_root);
514  gc_phase = Phase_mark;
515  markhp = NULL;
516}
517
518static void mark_slice (long work)
519{
520  value v, child;
521  mlsize_t i;
522
523  while (work > 0){
524    if (gray_vals_cur > gray_vals){
525      v = *--gray_vals_cur;
526      Assert (Is_gray_val (v));
527      Hd_val (v) = Blackhd_hd (Hd_val (v));
528      if (Tag_val (v) < No_scan_tag){
529	for (i = Wosize_val (v); i > 0;){
530	  --i;
531	  child = Field (v, i);
532	  darken (child);
533	}
534      } else if (Tag_val(v) == Weak_tag) {
535        *weak_arrays_cur++ = v;
536        if (weak_arrays_cur >= weak_arrays_end) realloc_weak_arrays ();
537      }
538      work -= Whsize_val (v);
539    }else if (markhp != NULL){
540      if (markhp == limit){
541	chunk = (((heap_chunk_head *) chunk) [-1]).next;
542	if (chunk == NULL){
543	  markhp = NULL;
544	}else{
545	  markhp = chunk;
546	  limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
547	}
548      }else{
549	if (Is_gray_val (Val_hp (markhp))){
550	  Assert (gray_vals_cur == gray_vals);
551	  *gray_vals_cur++ = Val_hp (markhp);
552	}
553	markhp += Bhsize_hp (markhp);
554      }
555    }else if (!heap_is_pure){
556      heap_is_pure = 1;
557      chunk = heap_start;
558      markhp = chunk;
559      limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
560    }else{
561      /* Marking is done. */
562      gc_sweep_hp = heap_start;
563      fl_init_merge ();
564      gc_phase = Phase_weak;
565      chunk = heap_start;
566      gc_sweep_hp = chunk;
567      limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
568      work = 0;
569    }
570  }
571}
572
573/* Reset weak pointers to objects that will be deallocated by the sweep phase
574 */
575
576static void weak_phase()
577{
578  value *c;
579  for (c = weak_arrays; c < weak_arrays_cur; c++)
580    { 
581      int i;
582      value arr = *c;
583      int len = Wosize_val(arr);
584      for (i=0; i < len; i++) 
585	{ 
586	  value v = Field(arr, i);
587	  if (Is_block(v) && Is_in_heap(v) && Is_white_val(v))
588	    Field(arr, i) = (value)NULL;
589	}
590    }
591  weak_arrays_cur = weak_arrays;
592  gc_phase = Phase_sweep;
593}
594
595static void sweep_slice (long work)
596{
597  char *hp;
598  header_t hd;
599
600  while (work > 0){
601    if (gc_sweep_hp < limit){
602      hp = gc_sweep_hp;
603      hd = Hd_hp (hp);
604      work -= Whsize_hd (hd);
605      gc_sweep_hp += Bhsize_hd (hd);
606      switch (Color_hd (hd)){
607      case White:
608	if (Tag_hd (hd) == Final_tag){
609	  Final_fun (Val_hp (hp)) (Val_hp (hp));
610	}
611	gc_sweep_hp = fl_merge_block (Bp_hp (hp));
612	break;
613      case Gray:
614	Assert (0);     /* Fall through to Black when not in debug mode. */
615      case Black:
616	Hd_hp (hp) = Whitehd_hd (hd);
617	break;
618      case Blue:
619	/* Only the blocks of the free-list are blue.  See [freelist.c]. */
620	fl_merge = Bp_hp (hp);
621	break;
622      }
623      Assert (gc_sweep_hp <= limit);
624    }else{
625      chunk = (((heap_chunk_head *) chunk) [-1]).next;
626      if (chunk == NULL){
627	/* Sweeping is done.  Start the next cycle. */
628        ++ stat_major_collections;
629	work = 0;
630	start_cycle ();
631      }else{
632	gc_sweep_hp = chunk;
633	limit = chunk + (((heap_chunk_head *) chunk) [-1]).size;
634      }
635    }
636  }
637}
638
639void major_collection_slice (void)
640{
641  /* Free memory at the start of the GC cycle:
642                 FM = stat_heap_size * percent_free / 100 * 2/3
643     Proportion of free memory consumed since the previous slice:
644                 PH = allocated_words / FM
645     Proportion of extra-heap memory consumed since the previous slice:
646                 PE = extra_heap_memory / stat_heap_size
647     Proportion of total work to do in this slice:
648                 P  = PH + PE
649     Amount of marking work for the GC cycle:
650                 MW = stat_heap_size * (100 - percent_free) / 100
651     Amount of sweeping work for the GC cycle:
652                 SW = stat_heap_size
653     Amount of marking work for this slice:
654                 MS = MW * 2 * P
655                 MS = 2 * (100 - percent_free)
656                      * (allocated_words * 3 / percent_free / 2
657		         + 100 * extra_heap_memory)
658     Amount of sweeping work for this slice:
659                 SS = SW * 2 * P
660                 SS = 2 * 100
661		      * (allocated_words * 3 / percent_free / 2
662		         + 100 * extra_heap_memory)
663     This slice will either mark MS words or sweep SS words.
664  */
665
666#define Margin 100  /* Make it a little faster to be on the safe side. */
667
668  if (gc_phase == Phase_mark){
669    mark_slice (2 * (100 - percent_free)
670		* (allocated_words * 3 / percent_free / 2
671                   + 100 * extra_heap_memory)
672		+ Margin);
673    gc_message ("!", 0);
674  }else if (gc_phase == Phase_weak){  
675    weak_phase();
676    gc_message (".", 0);
677  }else{
678    Assert (gc_phase == Phase_sweep);
679    sweep_slice (200 * (allocated_words * 3 / percent_free / 2
680			+ 100 * extra_heap_memory)
681		 + Margin);
682    gc_message ("$", 0);
683  }
684  stat_major_words += allocated_words;
685  allocated_words = 0;
686  extra_heap_memory = 0;
687}
688
689/* The minor heap must be empty when this function is called. */
690void finish_major_cycle (void)
691{
692
693  beg_gc_time();
694
695  if (gc_phase == Phase_mark) mark_slice (LONG_MAX);
696  if (gc_phase == Phase_weak) weak_phase();
697  Assert (gc_phase == Phase_sweep);
698  sweep_slice (LONG_MAX);
699  stat_major_words += allocated_words;
700  allocated_words = 0;
701
702  end_gc_time();
703
704}
705
706asize_t round_heap_chunk_size (asize_t request)
707{                            Assert (major_heap_increment >= Heap_chunk_min);
708  if (request < major_heap_increment){
709                              Assert (major_heap_increment % Page_size == 0);
710    return major_heap_increment;
711  }else if (request <= Heap_chunk_max){
712    return ((request + Page_size - 1) >> Page_log) << Page_log;
713  }else{
714    raise_out_of_memory ();
715  }
716  return 0;			/* Can't reach return */
717}
718
719void init_major_heap (asize_t heap_size)
720{
721  asize_t i;
722
723  stat_heap_size = round_heap_chunk_size (heap_size);
724  Assert (stat_heap_size % Page_size == 0);
725  heap_start = aligned_malloc (stat_heap_size + sizeof (heap_chunk_head),
726			       sizeof (heap_chunk_head));
727  if (heap_start == NULL)
728    fatal_error ("Fatal error: not enough memory for the initial heap.\n");
729  heap_start += sizeof (heap_chunk_head);
730  Assert ((unsigned long) heap_start % Page_size == 0);
731  (((heap_chunk_head *) heap_start) [-1]).size = stat_heap_size;
732  (((heap_chunk_head *) heap_start) [-1]).next = NULL;
733  heap_end = heap_start + stat_heap_size;
734  Assert ((unsigned long) heap_end % Page_size == 0);
735#ifdef SIXTEEN
736  page_table_size = 640L * 1024L / Page_size + 1;
737#else
738  page_table_size = 4 * stat_heap_size / Page_size;
739#endif
740  /*  page_table = (char *) malloc (page_table_size);
741  if (page_table == NULL){
742    fatal_error ("Fatal error: not enough memory for the initial heap.\n");
743  }
744  for (i = 0; i < page_table_size; i++){
745    page_table [i] = Not_in_heap;
746  }
747  for (i = Page (heap_start); i < Page (heap_end); i++){
748    page_table [i] = In_heap;
749  }
750  */
751  //  p_table_init(page_table_size);
752  p_table_init(64);
753  p_table_add_pages(heap_start, heap_end);
754  Hd_hp (heap_start) = Make_header (Wosize_bhsize (stat_heap_size), 0, Blue);
755  fl_init_merge ();
756  fl_merge_block (Bp_hp (heap_start));
757  /* We start the major GC in the marking phase, just after the roots have been
758     darkened. (Since there are no roots, we don't have to darken anything.) */
759  gc_phase = Phase_mark;
760  weak_arrays_size = 1;
761  weak_arrays = (value *) malloc (weak_arrays_size * sizeof (value));
762  weak_arrays_cur = weak_arrays;
763  weak_arrays_end = weak_arrays + weak_arrays_size;
764  gray_vals_size = 2048;
765  gray_vals = (value *) malloc (gray_vals_size * sizeof (value));
766  gray_vals_cur = gray_vals;
767  gray_vals_end = gray_vals + gray_vals_size;
768  heap_is_pure = 1;
769  allocated_words = 0;
770  extra_heap_memory = 0;
771}