diff options
Diffstat (limited to 'byterun')
-rw-r--r-- | byterun/alloc.c | 1 | ||||
-rw-r--r-- | byterun/config.h | 7 | ||||
-rw-r--r-- | byterun/gc_ctrl.c | 4 | ||||
-rw-r--r-- | byterun/minor_gc.c | 101 | ||||
-rw-r--r-- | byterun/minor_gc.h | 10 | ||||
-rw-r--r-- | byterun/roots.c | 13 | ||||
-rw-r--r-- | byterun/startup.c | 6 |
7 files changed, 93 insertions, 49 deletions
diff --git a/byterun/alloc.c b/byterun/alloc.c index 41dafdc4f..97d57b977 100644 --- a/byterun/alloc.c +++ b/byterun/alloc.c @@ -35,6 +35,7 @@ CAMLexport value alloc (mlsize_t wosize, tag_t tag) mlsize_t i; Assert (tag < 256); + Assert (tag != Infix_tag); if (wosize == 0){ result = Atom (tag); }else if (wosize <= Max_young_wosize){ diff --git a/byterun/config.h b/byterun/config.h index 812ab88cc..13276a197 100644 --- a/byterun/config.h +++ b/byterun/config.h @@ -124,11 +124,12 @@ typedef uint64 int64; /* Default speed setting for the major GC. The heap will grow until the dead objects and the free list represent this percentage of the - heap size. The rest of the heap is live objects. */ + total size of live objects. */ #define Percent_free_def 42 -/* Default setting for the compacter: off */ -#define Max_percent_free_def 1000000 +/* Default setting for the compacter: 300% + (i.e. trigger the compacter when 3/4 of the heap is free) */ +#define Max_percent_free_def 300 #endif /* _config_ */ diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c index 1871d8cc2..6d945359e 100644 --- a/byterun/gc_ctrl.c +++ b/byterun/gc_ctrl.c @@ -207,7 +207,7 @@ static value heap_stats (int returnstats) double majwords = stat_major_words + (double) allocated_words; long mincoll = stat_major_collections; long majcoll = stat_minor_collections; - long heapsz = stat_heap_size; + long heap_words = Wsize_bsize (stat_heap_size); long cpct = stat_compactions; res = alloc_tuple (14); @@ -216,7 +216,7 @@ static value heap_stats (int returnstats) Store_field (res, 2, copy_double (majwords)); Store_field (res, 3, Val_long (mincoll)); Store_field (res, 4, Val_long (majcoll)); - Store_field (res, 5, Val_long (heapsz)); + Store_field (res, 5, Val_long (heap_words)); Store_field (res, 6, Val_long (heap_chunks)); Store_field (res, 7, Val_long (live_words)); Store_field (res, 8, Val_long (live_blocks)); diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c index 78bb8ac7f..915053c08 100644 --- a/byterun/minor_gc.c +++ b/byterun/minor_gc.c @@ -67,7 +67,9 @@ void set_minor_heap_size (asize_t size) ref_table_end = ref_table + ref_table_size + ref_table_reserve; } -void oldify (value v, value *p) +static value oldify_todo_list = NULL; + +void oldify_one (value v, value *p) { value result, field0; header_t hd; @@ -78,40 +80,38 @@ void oldify (value v, value *p) if (Is_block (v) && Is_young (v)){ Assert (Hp_val (v) >= young_ptr); hd = Hd_val (v); - if (hd == 0){ /* Already forwarded ? */ - *p = Field (v, 0); /* Then the forward pointer is the first field. */ - }else if ((tag = Tag_hd (hd)), (tag == Infix_tag)) { - mlsize_t offset = Infix_offset_hd (hd); - oldify(v - offset, p); - *p += offset; - }else if (tag >= No_scan_tag){ - sz = Wosize_hd (hd); - result = alloc_shr (sz, tag); - for (i = 0; i < sz; i++) Field(result, i) = Field(v, i); - Hd_val (v) = 0; /* Put the forward flag. */ - Field (v, 0) = result; /* And the forward pointer. */ - *p = result; + if (hd == 0){ /* If already forwarded */ + *p = Field (v, 0); /* then forward pointer is first field. */ }else{ - /* We can do recursive calls before all the fields are filled, because - we will not be calling the major GC. */ - sz = Wosize_hd (hd); - result = alloc_shr (sz, tag); - *p = result; - field0 = Field (v, 0); - Hd_val (v) = 0; /* Put the forward flag. */ - Field (v, 0) = result; /* And the forward pointer. */ - if (sz == 1) { - p = &Field (result, 0); - v = field0; - goto tail_call; - } else { - oldify (field0, &Field (result, 0)); - for (i = 1; i < sz - 1; i++){ - oldify (Field(v, i), &Field (result, i)); - } - p = &Field (result, i); - v = Field (v, i); - goto tail_call; + tag = Tag_hd (hd); + if (tag >= No_scan_tag){ + sz = Wosize_hd (hd); + result = alloc_shr (sz, tag); + for (i = 0; i < sz; i++) Field (result, i) = Field (v, i); + Hd_val (v) = 0; /* Set forward flag */ + Field (v, 0) = result; /* and forward pointer. */ + *p = result; + }else if (tag == Infix_tag){ + mlsize_t offset = Infix_offset_hd (hd); + oldify_one (v - offset, p); /* This cannot recurse deeper than 1. */ + *p += offset; + }else{ + sz = Wosize_hd (hd); + result = alloc_shr (sz, tag); + *p = result; + field0 = Field (v, 0); + Hd_val (v) = 0; /* Set forward flag */ + Field (v, 0) = result; /* and forward pointer. */ + if (sz > 1){ + Field (result, 0) = field0; + Field (result, 1) = oldify_todo_list; /* Add this block */ + oldify_todo_list = v; /* to the "to do" list. */ + }else{ + Assert (sz == 1); + p = &Field (result, 0); + v = field0; + goto tail_call; + } } } }else{ @@ -119,6 +119,36 @@ void oldify (value v, value *p) } } +/* Finish the work that was put off by oldify_one. + Note that oldify_one itself is called by oldify_mopup, so we + have to be careful to remove the first entry from the list before + oldifying its fields. */ +void oldify_mopup (void) +{ + value v, new_v, f; + mlsize_t i; + + while (oldify_todo_list != NULL){ + v = oldify_todo_list; /* Get the head. */ + Assert (Hd_val (v) == 0); /* It must be forwarded. */ + new_v = Field (v, 0); /* Follow forward pointer. */ + oldify_todo_list = Field (new_v, 1); /* Remove from list. */ + + f = Field (new_v, 0); + if (Is_block (f) && Is_young (f)){ + oldify_one (f, &Field (new_v, 0)); + } + for (i = 1; i < Wosize_val (new_v); i++){ + f = Field (v, i); + if (Is_block (f) && Is_young (f)){ + oldify_one (Field (v, i), &Field (new_v, i)); + }else{ + Field (new_v, i) = f; + } + } + } +} + /* Make sure the minor heap is empty by performing a minor collection if needed. */ @@ -130,7 +160,8 @@ void empty_minor_heap (void) in_minor_collection = 1; gc_message (0x02, "<", 0); oldify_local_roots(); - for (r = ref_table; r < ref_table_ptr; r++) oldify (**r, *r); + for (r = ref_table; r < ref_table_ptr; r++) oldify_one (**r, *r); + oldify_mopup (); if (young_ptr < young_limit) young_ptr = young_limit; stat_minor_words += Wsize_bsize (young_end - young_ptr); young_ptr = young_end; diff --git a/byterun/minor_gc.h b/byterun/minor_gc.h index 66252aeb2..d520d98c7 100644 --- a/byterun/minor_gc.h +++ b/byterun/minor_gc.h @@ -32,6 +32,14 @@ extern void empty_minor_heap (void); CAMLextern void minor_collection (void); CAMLextern void garbage_collection (void); /* for the native-code system */ extern void realloc_ref_table (void); -extern void oldify (value, value *); +extern void oldify_one (value, value *); +extern void oldify_mopup (void); + +#define Oldify(p) do{ \ + value __oldify__v__ = *p; \ + if (Is_block (__oldify__v__) && Is_young (__oldify__v__)){ \ + oldify_one (__oldify__v__, (p)); \ + } \ + }while(0) #endif /* _minor_gc_ */ diff --git a/byterun/roots.c b/byterun/roots.c index 391789c9e..6378ceffb 100644 --- a/byterun/roots.c +++ b/byterun/roots.c @@ -30,7 +30,8 @@ CAMLexport struct caml__roots_block *local_roots = NULL; void (*scan_roots_hook) (scanning_action f) = NULL; /* FIXME rename to [oldify_young_roots] and synchronise with asmrun/roots.c */ -/* Call [oldify] on (at least) all the roots that point to the minor heap. */ +/* Call [oldify_one] on (at least) all the roots that point to the minor + heap. */ void oldify_local_roots (void) { register value * sp; @@ -40,25 +41,25 @@ void oldify_local_roots (void) /* The stack */ for (sp = extern_sp; sp < stack_high; sp++) { - oldify (*sp, sp); + oldify_one (*sp, sp); } /* Local C roots */ /* FIXME do the old-frame trick ? */ for (lr = local_roots; lr != NULL; lr = lr->next) { for (i = 0; i < lr->ntables; i++){ for (j = 0; j < lr->nitems; j++){ sp = &(lr->tables[i][j]); - oldify (*sp, sp); + oldify_one (*sp, sp); } } } /* Global C roots */ for (gr = caml_global_roots.forward[0]; gr != NULL; gr = gr->forward[0]) { - oldify(*(gr->root), gr->root); + oldify_one(*(gr->root), gr->root); } /* Finalised values */ - final_do_young_roots (&oldify); + final_do_young_roots (&oldify_one); /* Hook */ - if (scan_roots_hook != NULL) (*scan_roots_hook)(&oldify); + if (scan_roots_hook != NULL) (*scan_roots_hook)(&oldify_one); } /* Call [darken] on all roots */ diff --git a/byterun/startup.c b/byterun/startup.c index db69dc5ae..a2dddd662 100644 --- a/byterun/startup.c +++ b/byterun/startup.c @@ -376,7 +376,8 @@ CAMLexport void caml_main(char **argv) close_channel(chan); /* this also closes fd */ stat_free(trail.section); /* Ensure that the globals are in the major heap. */ - oldify(global_data, &global_data); + oldify_one (global_data, &global_data); + oldify_mopup (); /* Initialize system libraries */ init_exceptions(); sys_init(argv + pos); @@ -429,7 +430,8 @@ CAMLexport void caml_startup_code(code_t code, asize_t code_size, /* Load the globals */ global_data = input_val_from_string((value)data, 0); /* Ensure that the globals are in the major heap. */ - oldify(global_data, &global_data); + oldify_one (global_data, &global_data); + oldify_mopup (); /* Run the code */ init_exceptions(); sys_init(argv); |