diff --git a/byterun/finalise.c b/byterun/finalise.c index 7e41e350d..a01dd1bda 100644 --- a/byterun/finalise.c +++ b/byterun/finalise.c @@ -29,8 +29,12 @@ struct final { int offset; }; -static struct final *final_table = NULL; -static uintnat old = 0, young = 0, size = 0; +struct finalisable { + struct final *table; + uintnat old; + uintnat young; + uintnat size; +}; /* [0..old) : finalisable set, the values are in the major heap [old..young) : recent set, the values could be in the minor heap [young..size) : free space @@ -39,6 +43,8 @@ static uintnat old = 0, young = 0, size = 0; below when the value are unreachable (for the first time). */ +static struct finalisable finalisable_first = {NULL,0,0,0}; + struct to_do { struct to_do *next; int size; @@ -76,16 +82,16 @@ static void alloc_to_do (int size) /* Find white finalisable values, move them to the finalising set, and darken them. */ -void caml_final_update (void) +static void generic_final_update (struct finalisable * final) { uintnat i, j, k; uintnat todo_count = 0; - Assert (old <= young); - for (i = 0; i < old; i++){ - Assert (Is_block (final_table[i].val)); - Assert (Is_in_heap (final_table[i].val)); - if (Is_white_val (final_table[i].val)) ++ todo_count; + Assert (final->old <= final->young); + for (i = 0; i < final->old; i++){ + Assert (Is_block (final->table[i].val)); + Assert (Is_in_heap (final->table[i].val)); + if (Is_white_val (final->table[i].val)) ++ todo_count; } /** invariant: @@ -100,22 +106,22 @@ void caml_final_update (void) if (todo_count > 0){ alloc_to_do (todo_count); j = k = 0; - for (i = 0; i < old; i++){ - Assert (Is_block (final_table[i].val)); - Assert (Is_in_heap (final_table[i].val)); - Assert (Tag_val (final_table[i].val) != Forward_tag); - if (Is_white_val (final_table[i].val)){ - to_do_tl->item[k++] = final_table[i]; + for (i = 0; i < final->old; i++){ + Assert (Is_block (final->table[i].val)); + Assert (Is_in_heap (final->table[i].val)); + Assert (Tag_val (final->table[i].val) != Forward_tag); + if (Is_white_val (final->table[i].val)){ + to_do_tl->item[k++] = final->table[i]; }else{ - final_table[j++] = final_table[i]; + final->table[j++] = final->table[i]; } } - CAMLassert (i == old); - old = j; - for(;i < young; i++){ - final_table[j++] = final_table[i]; + CAMLassert (i == final->old); + final->old = j; + for(;i < final->young; i++){ + final->table[j++] = final->table[i]; } - young = j; + final->young = j; to_do_tl->size = k; for (i = 0; i < k; i++){ /* Note that item may already be dark due to multiple entries in @@ -125,6 +131,11 @@ void caml_final_update (void) } } +void caml_final_update (){ + generic_final_update(&finalisable_first); +} + + static int running_finalisation_function = 0; /* Call the finalisation functions for the finalising set. @@ -168,13 +179,15 @@ void caml_final_do_calls (void) This is called by the major GC [caml_darken_all_roots] and by the compactor through [caml_do_roots] */ -void caml_final_do_roots (scanning_action f) +void caml_final_do_roots (scanning_action f, struct finalisable *final) { uintnat i; struct to_do *todo; - Assert (old <= young); - for (i = 0; i < young; i++) Call_action (f, final_table[i].fun); + Assert (finalisable_first.old <= finalisable_first.young); + for (i = 0; i < finalisable_first.young; i++){ + Call_action (f, finalisable_first.table[i].fun); + }; for (todo = to_do_hd; todo != NULL; todo = todo->next){ for (i = 0; i < todo->size; i++){ @@ -191,9 +204,10 @@ void caml_final_invert_finalisable_values () { uintnat i; - CAMLassert (old <= young); - for (i = 0; i < young; i++){ - invert_root(final_table[i].val,&final_table[i].val); + CAMLassert (finalisable_first.old <= finalisable_first.young); + for (i = 0; i < finalisable_first.young; i++){ + invert_root(finalisable_first.table[i].val, + &finalisable_first.table[i].val); }; } @@ -204,10 +218,12 @@ void caml_final_do_young_roots () { uintnat i; - Assert (old <= young); - for (i = old; i < young; i++){ - caml_oldify_one(final_table[i].fun, &final_table[i].fun); - caml_oldify_one(final_table[i].val, &final_table[i].val); + Assert (finalisable_first.old <= finalisable_first.young); + for (i = finalisable_first.old; i < finalisable_first.young; i++){ + caml_oldify_one(finalisable_first.table[i].fun, + &finalisable_first.table[i].fun); + caml_oldify_one(finalisable_first.table[i].val, + &finalisable_first.table[i].val); } } @@ -217,11 +233,11 @@ void caml_final_do_young_roots () */ void caml_final_empty_young (void) { - old = young; + finalisable_first.old = finalisable_first.young; } /* Put (f,v) in the recent set. */ -CAMLprim value caml_final_register (value f, value v) +static void generic_final_register (struct finalisable *final, value f, value v) { if (!Is_block (v) || !Is_in_heap_or_young(v) @@ -230,36 +246,41 @@ CAMLprim value caml_final_register (value f, value v) || Tag_val (v) == Forward_tag) { caml_invalid_argument ("Gc.finalise"); } - Assert (old <= young); + Assert (final->old <= final->young); - if (young >= size){ - if (final_table == NULL){ + if (final->young >= final->size){ + if (final->table == NULL){ uintnat new_size = 30; - final_table = caml_stat_alloc (new_size * sizeof (struct final)); - Assert (old == 0); - Assert (young == 0); - size = new_size; + final->table = caml_stat_alloc (new_size * sizeof (struct final)); + Assert (final->old == 0); + Assert (final->young == 0); + final->size = new_size; }else{ - uintnat new_size = size * 2; - final_table = caml_stat_resize (final_table, + uintnat new_size = final->size * 2; + final->table = caml_stat_resize (final->table, new_size * sizeof (struct final)); - size = new_size; + final->size = new_size; } } - Assert (young < size); - final_table[young].fun = f; + Assert (final->young < final->size); + final->table[final->young].fun = f; if (Tag_val (v) == Infix_tag){ - final_table[young].offset = Infix_offset_val (v); - final_table[young].val = v - Infix_offset_val (v); + final->table[final->young].offset = Infix_offset_val (v); + final->table[final->young].val = v - Infix_offset_val (v); }else{ - final_table[young].offset = 0; - final_table[young].val = v; + final->table[final->young].offset = 0; + final->table[final->young].val = v; } - ++ young; + ++ final->young; +} + +CAMLprim value caml_final_register (value f, value v){ + generic_final_register(&finalisable_first, f, v); return Val_unit; } + CAMLprim value caml_final_release (value unit) { running_finalisation_function = 0;