mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-15 00:37:35 +02:00
Added heap write barrier
This commit is contained in:
parent
ae3ba3cd1a
commit
f1443979e6
3 changed files with 45 additions and 24 deletions
62
gc.c
62
gc.c
|
@ -504,31 +504,45 @@ PHASE 2 - multi-threaded mutator (IE, more than one stack thread):
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
// GC functions called by the Mutator threads
|
// GC functions called by the Mutator threads
|
||||||
|
|
||||||
void gc_mut_update(object heapO)
|
// Write barrier for updates to heap-allocated objects
|
||||||
|
void gc_mut_update(gc_thread_data *thd, object old_obj, object value)
|
||||||
{
|
{
|
||||||
// TODO: how does this fit in with the write buffer?
|
int status = ATOMIC_GET(&gc_status_col),
|
||||||
// this part is important, especially during tracing
|
stage = ATOMIC_GET(&gc_stage);
|
||||||
|
if (thd->gc_status != STATUS_ASYNC) {
|
||||||
the paper marks both the heap location being written to and the
|
gc_mark_gray(thd, old_obj);
|
||||||
value being written. not sure it makes sense to mark the value
|
gc_mark_gray(thd, value);
|
||||||
as it will always be on the stack - issue is if any obj's it is
|
} else if (stage == STAGE_TRACING) {
|
||||||
referencing are on the heap. this is where that stack bit might
|
gc_mark_gray(thd, old_obj);
|
||||||
come in handy.
|
}
|
||||||
|
// TODO: concerned there may be an issue here with a stack object
|
||||||
do we want to mark gray immediately during add mutator, or wait
|
// having a 'tree' of references that contains heap objects. these
|
||||||
until minor GC? YES - I think for mutators we need to mark the
|
// objects would be skipped and would never be grayed by the current
|
||||||
object gray immediately. otherwise if we delay until GC, a sweep
|
// code:
|
||||||
may have already finished up and freed such an obj that would
|
//
|
||||||
otherwise not have been freed if we had waited.
|
// the paper marks both the heap location being written to and the
|
||||||
|
// value being written. not sure it makes sense to mark the value
|
||||||
again, only potential issue seems to be if a stack obj could ref
|
// as it will always be on the stack - issue is if any obj's it is
|
||||||
something else on the heap - can that happen? I think this can only
|
// referencing are on the heap. this is where that stack bit might
|
||||||
happen if the heap obj it refs is linked to a root, because stack
|
// come in handy.
|
||||||
objs are so short lived??
|
//
|
||||||
|
// do we want to mark gray immediately during add mutator, or wait
|
||||||
also we already know if objects are on the stack due to their color (RED).
|
// until minor GC? YES - I think for mutators we need to mark the
|
||||||
so can use this to not mark red values. otherwise probably do want
|
// object gray immediately. otherwise if we delay until GC, a sweep
|
||||||
to mark the 'y' as well (per paper) to prevent timing issues when we wait
|
// may have already finished up and freed such an obj that would
|
||||||
|
// otherwise not have been freed if we had waited.
|
||||||
|
//
|
||||||
|
// again, only potential issue seems to be if a stack obj could ref
|
||||||
|
// something else on the heap - can that happen? I think this can only
|
||||||
|
// happen if the heap obj it refs is linked to a root, because stack
|
||||||
|
// objs are so short lived??
|
||||||
|
//
|
||||||
|
// also we already know if objects are on the stack due to their color (RED).
|
||||||
|
// so can use this to not mark red values. otherwise probably do want
|
||||||
|
// to mark the 'y' as well (per paper) to prevent timing issues when we wait
|
||||||
|
//
|
||||||
|
// do have some concern though that mark_gray will stop when a stack obj
|
||||||
|
// is detected, and the code will not examine any refs held by the stack obj.
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: still need to handle case where a mutator is blocked
|
// TODO: still need to handle case where a mutator is blocked
|
||||||
|
|
|
@ -142,6 +142,7 @@ void gc_thr_add_to_move_buffer(gc_thread_data *d, int *alloci, object obj);
|
||||||
void gc_thread_data_init(gc_thread_data *thd, int mut_num, char *stack_base, long stack_size);
|
void gc_thread_data_init(gc_thread_data *thd, int mut_num, char *stack_base, long stack_size);
|
||||||
void gc_thread_data_free(gc_thread_data *thd);
|
void gc_thread_data_free(gc_thread_data *thd);
|
||||||
// Prototypes for mutator/collector:
|
// Prototypes for mutator/collector:
|
||||||
|
void gc_mut_update(gc_thread_data *thd, object old_obj, object value);
|
||||||
void gc_mut_cooperate(gc_thread_data *thd);
|
void gc_mut_cooperate(gc_thread_data *thd);
|
||||||
void gc_mark_gray(gc_thread_data *thd, object obj);
|
void gc_mark_gray(gc_thread_data *thd, object obj);
|
||||||
void gc_collector_trace();
|
void gc_collector_trace();
|
||||||
|
|
|
@ -775,6 +775,7 @@ object Cyc_eq(object x, object y) {
|
||||||
|
|
||||||
object Cyc_set_car(void *data, object l, object val) {
|
object Cyc_set_car(void *data, object l, object val) {
|
||||||
if (Cyc_is_cons(l) == boolean_f) Cyc_invalid_type_error(data, cons_tag, l);
|
if (Cyc_is_cons(l) == boolean_f) Cyc_invalid_type_error(data, cons_tag, l);
|
||||||
|
gc_mut_update((gc_thread_data *)data, car(l), val);
|
||||||
car(l) = val;
|
car(l) = val;
|
||||||
add_mutation(l, val);
|
add_mutation(l, val);
|
||||||
return l;
|
return l;
|
||||||
|
@ -782,6 +783,7 @@ object Cyc_set_car(void *data, object l, object val) {
|
||||||
|
|
||||||
object Cyc_set_cdr(void *data, object l, object val) {
|
object Cyc_set_cdr(void *data, object l, object val) {
|
||||||
if (Cyc_is_cons(l) == boolean_f) Cyc_invalid_type_error(data, cons_tag, l);
|
if (Cyc_is_cons(l) == boolean_f) Cyc_invalid_type_error(data, cons_tag, l);
|
||||||
|
gc_mut_update((gc_thread_data *)data, cdr(l), val);
|
||||||
cdr(l) = val;
|
cdr(l) = val;
|
||||||
add_mutation(l, val);
|
add_mutation(l, val);
|
||||||
return l;
|
return l;
|
||||||
|
@ -797,6 +799,10 @@ object Cyc_vector_set(void *data, object v, object k, object obj) {
|
||||||
Cyc_rt_raise2(data, "vector-set! - invalid index", k);
|
Cyc_rt_raise2(data, "vector-set! - invalid index", k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gc_mut_update((gc_thread_data *)data,
|
||||||
|
((vector)v)->elts[idx],
|
||||||
|
obj);
|
||||||
|
|
||||||
((vector)v)->elts[idx] = obj;
|
((vector)v)->elts[idx] = obj;
|
||||||
// TODO: probably could be more efficient here and also pass
|
// TODO: probably could be more efficient here and also pass
|
||||||
// index, so only that one entry needs GC.
|
// index, so only that one entry needs GC.
|
||||||
|
|
Loading…
Add table
Reference in a new issue