mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-24 20:45:06 +02:00
New write barrier implementation
This commit is contained in:
parent
c8878e749a
commit
33447ebc57
3 changed files with 39 additions and 28 deletions
35
gc.c
35
gc.c
|
@ -821,13 +821,12 @@ void gc_mut_update(gc_thread_data *thd, object old_obj, object value)
|
||||||
gc_mark_gray(thd, old_obj);
|
gc_mark_gray(thd, old_obj);
|
||||||
// Check if value is on the heap. If so, mark gray right now,
|
// Check if value is on the heap. If so, mark gray right now,
|
||||||
// otherwise set it to be marked after moved to heap by next GC
|
// otherwise set it to be marked after moved to heap by next GC
|
||||||
// if (gc_is_stack_obj(thd, value)) {
|
if (gc_is_stack_obj(thd, value)) {
|
||||||
// grayed(value) = 1;
|
grayed(value) = 1;
|
||||||
// } else {
|
} else {
|
||||||
// gc_mark_gray(thd, value);
|
gc_mark_gray(thd, value);
|
||||||
// }
|
}
|
||||||
pthread_mutex_unlock(&(thd->lock));
|
pthread_mutex_unlock(&(thd->lock));
|
||||||
gc_stack_mark_gray(thd, value); // TODO: this line will be replace with above block
|
|
||||||
} else if (stage == STAGE_TRACING) {
|
} else if (stage == STAGE_TRACING) {
|
||||||
//fprintf(stderr, "DEBUG - GC async tracing marking heap obj %p ", old_obj);
|
//fprintf(stderr, "DEBUG - GC async tracing marking heap obj %p ", old_obj);
|
||||||
//Cyc_display(old_obj, stderr);
|
//Cyc_display(old_obj, stderr);
|
||||||
|
@ -877,12 +876,20 @@ gc_stack_mark_gray(thd, value); // TODO: this line will be replace with above bl
|
||||||
void gc_mut_cooperate(gc_thread_data *thd, int buf_len)
|
void gc_mut_cooperate(gc_thread_data *thd, int buf_len)
|
||||||
{
|
{
|
||||||
int i, status = ATOMIC_GET(&gc_status_col);
|
int i, status = ATOMIC_GET(&gc_status_col);
|
||||||
|
|
||||||
|
// Handle any pending marks from write barrier
|
||||||
|
pthread_mutex_lock(&(thd->lock));
|
||||||
|
thd->last_write += thd->pending_writes;
|
||||||
|
thd->pending_writes = 0;
|
||||||
|
pthread_mutex_unlock(&(thd->lock));
|
||||||
|
|
||||||
if (thd->gc_status != status) {
|
if (thd->gc_status != status) {
|
||||||
if (thd->gc_status == STATUS_ASYNC) {
|
if (thd->gc_status == STATUS_ASYNC) {
|
||||||
// Async is done, so clean up old mark data from the last collection
|
// Async is done, so clean up old mark data from the last collection
|
||||||
pthread_mutex_lock(&(thd->lock));
|
pthread_mutex_lock(&(thd->lock));
|
||||||
thd->last_write = 0;
|
thd->last_write = 0;
|
||||||
thd->last_read = 0;
|
thd->last_read = 0;
|
||||||
|
thd->pending_writes = 0;
|
||||||
pthread_mutex_unlock(&(thd->lock));
|
pthread_mutex_unlock(&(thd->lock));
|
||||||
}
|
}
|
||||||
else if (thd->gc_status == STATUS_SYNC2) {
|
else if (thd->gc_status == STATUS_SYNC2) {
|
||||||
|
@ -941,6 +948,17 @@ void gc_mark_gray(gc_thread_data *thd, object obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc_mark_gray2(gc_thread_data *thd, object obj)
|
||||||
|
{
|
||||||
|
if (is_object_type(obj) && mark(obj) == gc_color_clear) {
|
||||||
|
thd->mark_buffer = vpbuffer_add(thd->mark_buffer,
|
||||||
|
&(thd->mark_buffer_len),
|
||||||
|
(thd->last_write + thd->pending_writes),
|
||||||
|
obj);
|
||||||
|
thd->pending_writes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: before doing this, may want to debug a bit and see what is
|
// TODO: before doing this, may want to debug a bit and see what is
|
||||||
// being passed to gc_mut_update. see if those objects tend to have
|
// being passed to gc_mut_update. see if those objects tend to have
|
||||||
// any heap refs. may need to add debug code to do that...
|
// any heap refs. may need to add debug code to do that...
|
||||||
|
@ -1003,7 +1021,10 @@ void gc_collector_trace()
|
||||||
if (clean) {
|
if (clean) {
|
||||||
pthread_mutex_lock(&(m->lock));
|
pthread_mutex_lock(&(m->lock));
|
||||||
if (m->last_read < m->last_write) {
|
if (m->last_read < m->last_write) {
|
||||||
printf("JAE DEBUG - might have exited trace early\n");
|
fprintf(stderr, "JAE DEBUG - might have exited trace early\n");
|
||||||
|
clean = 0;
|
||||||
|
}
|
||||||
|
else if (m->pending_writes) {
|
||||||
clean = 0;
|
clean = 0;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&(m->lock));
|
pthread_mutex_unlock(&(m->lock));
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct gc_thread_data_t {
|
||||||
int gc_status;
|
int gc_status;
|
||||||
int last_write;
|
int last_write;
|
||||||
int last_read;
|
int last_read;
|
||||||
|
int pending_writes;
|
||||||
void **mark_buffer;
|
void **mark_buffer;
|
||||||
int mark_buffer_len;
|
int mark_buffer_len;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
@ -164,6 +165,7 @@ void gc_mut_cooperate(gc_thread_data *thd, int buf_len);
|
||||||
void gc_stack_mark_refs_gray(gc_thread_data *thd, object obj, int depth);
|
void gc_stack_mark_refs_gray(gc_thread_data *thd, object obj, int depth);
|
||||||
void gc_stack_mark_gray(gc_thread_data *thd, object obj);
|
void gc_stack_mark_gray(gc_thread_data *thd, object obj);
|
||||||
void gc_mark_gray(gc_thread_data *thd, object obj);
|
void gc_mark_gray(gc_thread_data *thd, object obj);
|
||||||
|
void gc_mark_gray2(gc_thread_data *thd, object obj);
|
||||||
void gc_collector_trace();
|
void gc_collector_trace();
|
||||||
void gc_mark_black(object obj);
|
void gc_mark_black(object obj);
|
||||||
void gc_collector_mark_gray(object parent, object obj);
|
void gc_collector_mark_gray(object parent, object obj);
|
||||||
|
|
30
runtime.c
30
runtime.c
|
@ -2452,35 +2452,24 @@ void gc_mark_globals()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *gc_fixup_moved_obj(gc_thread_data *thd, int *alloci, int *num_grayed, char *obj, object hp)
|
char *gc_fixup_moved_obj(gc_thread_data *thd, int *alloci, char *obj, object hp)
|
||||||
{
|
{
|
||||||
|
if (grayed(obj)) {
|
||||||
|
pthread_mutex_lock(&(thd->lock));
|
||||||
|
gc_mark_gray2(thd, hp);
|
||||||
|
pthread_mutex_unlock(&(thd->lock));
|
||||||
|
}
|
||||||
|
|
||||||
// hp ==> new heap object, point to it from old stack object
|
// hp ==> new heap object, point to it from old stack object
|
||||||
forward(obj) = hp;
|
forward(obj) = hp;
|
||||||
type_of(obj) = forward_tag;
|
type_of(obj) = forward_tag;
|
||||||
// keep track of each allocation so we can scan/move
|
// keep track of each allocation so we can scan/move
|
||||||
// the whole live object 'tree'
|
// the whole live object 'tree'
|
||||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||||
|
|
||||||
// TODO: if grayed(obj) then - do a deferred gc_mark_gray on hp
|
|
||||||
// you know, one possibility would be to add it to the thread mark buffer
|
|
||||||
// but now increment the read (write?) variable. instead increment another
|
|
||||||
// one and wait until the end of minor GC to set read (write?) to the
|
|
||||||
// appropriate value. just need to make sure we have the lock before
|
|
||||||
// updating it.
|
|
||||||
// that should avoid race conditions and the need for an additional buffer
|
|
||||||
|
|
||||||
if (TODO){
|
|
||||||
lock
|
|
||||||
gc_mark_gray - but WITHOUT incrementing write (read?)
|
|
||||||
unlock
|
|
||||||
(*num_grayed)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return (char *)hp;
|
return (char *)hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown, int *num_grayed) {
|
char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown) {
|
||||||
if (!is_object_type(obj)) return obj;
|
if (!is_object_type(obj)) return obj;
|
||||||
switch(type_of(obj)){
|
switch(type_of(obj)){
|
||||||
case cons_tag: {
|
case cons_tag: {
|
||||||
|
@ -2562,7 +2551,7 @@ char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown, int
|
||||||
temp = obj; \
|
temp = obj; \
|
||||||
if (check_overflow(low_limit, temp) && \
|
if (check_overflow(low_limit, temp) && \
|
||||||
check_overflow(temp, high_limit)){ \
|
check_overflow(temp, high_limit)){ \
|
||||||
(obj) = (object) gc_move(temp, (gc_thread_data *)data, &alloci, &heap_grown, &num_grayed); \
|
(obj) = (object) gc_move(temp, (gc_thread_data *)data, &alloci, &heap_grown); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2575,7 +2564,6 @@ void GC(void *data, closure cont, object *args, int num_args)
|
||||||
int i;
|
int i;
|
||||||
int scani = 0, alloci = 0;
|
int scani = 0, alloci = 0;
|
||||||
int heap_grown = 0;
|
int heap_grown = 0;
|
||||||
int num_grayed = 0;
|
|
||||||
|
|
||||||
//fprintf(stdout, "DEBUG, started minor GC\n"); // JAE DEBUG
|
//fprintf(stdout, "DEBUG, started minor GC\n"); // JAE DEBUG
|
||||||
// Prevent overrunning buffer
|
// Prevent overrunning buffer
|
||||||
|
|
Loading…
Add table
Reference in a new issue