Working on gc_collector()

This commit is contained in:
Justin Ethier 2015-11-10 21:16:40 -05:00
parent d3a6418b0b
commit 41f2a9e6ca
3 changed files with 108 additions and 89 deletions

102
gc.c
View file

@ -178,48 +178,48 @@ size_t gc_heap_total_size(gc_heap *h)
return total_size; return total_size;
} }
void gc_mark(gc_heap *h, object obj) //void gc_mark(gc_heap *h, object obj)
{ //{
if (nullp(obj) || is_value_type(obj) || mark(obj)) // if (nullp(obj) || is_value_type(obj) || mark(obj))
return; // return;
//
#if GC_DEBUG_PRINTFS //#if GC_DEBUG_PRINTFS
// fprintf(stdout, "gc_mark %p\n", obj); //// fprintf(stdout, "gc_mark %p\n", obj);
#endif //#endif
((list)obj)->hdr.mark = 1; // ((list)obj)->hdr.mark = 1;
// TODO: mark heap saves (??) // // TODO: mark heap saves (??)
// could this be a write barrier? // // could this be a write barrier?
//
// Mark objects this one references // // Mark objects this one references
if (type_of(obj) == cons_tag) { // if (type_of(obj) == cons_tag) {
gc_mark(h, car(obj)); // gc_mark(h, car(obj));
gc_mark(h, cdr(obj)); // gc_mark(h, cdr(obj));
} else if (type_of(obj) == closure1_tag) { // } else if (type_of(obj) == closure1_tag) {
gc_mark(h, ((closure1) obj)->elt1); // gc_mark(h, ((closure1) obj)->elt1);
} else if (type_of(obj) == closure2_tag) { // } else if (type_of(obj) == closure2_tag) {
gc_mark(h, ((closure2) obj)->elt1); // gc_mark(h, ((closure2) obj)->elt1);
gc_mark(h, ((closure2) obj)->elt2); // gc_mark(h, ((closure2) obj)->elt2);
} else if (type_of(obj) == closure3_tag) { // } else if (type_of(obj) == closure3_tag) {
gc_mark(h, ((closure3) obj)->elt1); // gc_mark(h, ((closure3) obj)->elt1);
gc_mark(h, ((closure3) obj)->elt2); // gc_mark(h, ((closure3) obj)->elt2);
gc_mark(h, ((closure3) obj)->elt3); // gc_mark(h, ((closure3) obj)->elt3);
} else if (type_of(obj) == closure4_tag) { // } else if (type_of(obj) == closure4_tag) {
gc_mark(h, ((closure4) obj)->elt1); // gc_mark(h, ((closure4) obj)->elt1);
gc_mark(h, ((closure4) obj)->elt2); // gc_mark(h, ((closure4) obj)->elt2);
gc_mark(h, ((closure4) obj)->elt3); // gc_mark(h, ((closure4) obj)->elt3);
gc_mark(h, ((closure4) obj)->elt4); // gc_mark(h, ((closure4) obj)->elt4);
} else if (type_of(obj) == closureN_tag) { // } else if (type_of(obj) == closureN_tag) {
int i, n = ((closureN) obj)->num_elt; // int i, n = ((closureN) obj)->num_elt;
for (i = 0; i < n; i++) { // for (i = 0; i < n; i++) {
gc_mark(h, ((closureN) obj)->elts[i]); // gc_mark(h, ((closureN) obj)->elts[i]);
} // }
} else if (type_of(obj) == vector_tag) { // } else if (type_of(obj) == vector_tag) {
int i, n = ((vector) obj)->num_elt; // int i, n = ((vector) obj)->num_elt;
for (i = 0; i < n; i++) { // for (i = 0; i < n; i++) {
gc_mark(h, ((vector) obj)->elts[i]); // gc_mark(h, ((vector) obj)->elts[i]);
} // }
} // }
} //}
size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr) size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr)
{ {
@ -670,28 +670,30 @@ void gc_collector()
int tmp; int tmp;
// TODO: what kind of sync is required here? // TODO: what kind of sync is required here?
//clear //clear :
gc_stage = STAGE_CLEAR_OR_MARKING; gc_stage = STAGE_CLEAR_OR_MARKING;
// exchange values of markColor and clearColor // exchange values of markColor and clearColor
// TODO: synchronize?
tmp = gc_color_clear; tmp = gc_color_clear;
gc_color_clear = gc_color_mark; gc_color_clear = gc_color_mark;
gc_color_mark = tmp; gc_color_mark = tmp;
gc_handshake(STATUS_SYNC1); gc_handshake(STATUS_SYNC1);
//mark: //mark :
gc_handshake(STATUS_SYNC2) gc_handshake(STATUS_SYNC2)
gc_stage = STAGE_TRACING; gc_stage = STAGE_TRACING;
gc_post_handshake(STATUS_ASYNC); gc_post_handshake(STATUS_ASYNC);
TODO: mark global roots gc_mark_globals();
gc_wait_handshake(); gc_wait_handshake();
//trace : //trace :
CollectorTrace() gc_collector_trace();
gc_stage = STAGE_SWEEPING; gc_stage = STAGE_SWEEPING;
//sweep : //sweep :
For each object x in the heap: // TODO: For each object x in the heap:
if (color(x) = clearColor) // TODO: if (color(x) = clearColor)
free free [ x // TODO: free free [ x
color(x) blue // TODO: color(x) blue
gc_stage = STAGE_RESTING; gc_stage = STAGE_RESTING;
// TODO: how long to rest?
} }
///////////////////////////////////////////// /////////////////////////////////////////////

View file

@ -133,9 +133,10 @@ void *gc_alloc(gc_heap *h, size_t size, int *heap_grown);
size_t gc_allocated_bytes(object obj); size_t gc_allocated_bytes(object obj);
gc_heap *gc_heap_last(gc_heap *h); gc_heap *gc_heap_last(gc_heap *h);
size_t gc_heap_total_size(gc_heap *h); size_t gc_heap_total_size(gc_heap *h);
void gc_mark(gc_heap *h, object obj); //size_t gc_collect(gc_heap *h, size_t *sum_freed);
//void gc_mark(gc_heap *h, object obj);
void gc_mark_globals(void);
size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr); size_t gc_sweep(gc_heap *h, size_t *sum_freed_ptr);
size_t gc_collect(gc_heap *h, size_t *sum_freed);
void gc_thr_grow_move_buffer(gc_thread_data *d); void gc_thr_grow_move_buffer(gc_thread_data *d);
void gc_thr_add_to_move_buffer(gc_thread_data *d, int *alloci, object obj); 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);

View file

@ -2362,34 +2362,50 @@ void Cyc_start_thread(gc_thread_data *thd)
exit(0); exit(0);
} }
// Collect garbage using mark&sweep algorithm //// Collect garbage using mark&sweep algorithm
// Note non-global roots should be marked prior to calling this function. //// Note non-global roots should be marked prior to calling this function.
size_t gc_collect(gc_heap *h, size_t *sum_freed) //size_t gc_collect(gc_heap *h, size_t *sum_freed)
//{
//#if GC_DEBUG_CONCISE_PRINTFS
// printf("(heap: %p size: %d)\n", h, (unsigned int)gc_heap_total_size(h));
//#endif
// // Mark global variables
// gc_mark(h, Cyc_global_variables); // Internal global used by the runtime
// // Marking it ensures all glos are marked
// {
// list l = global_table;
// for(; !nullp(l); l = cdr(l)){
// cvar_type *c = (cvar_type *)car(l);
// gc_mark(h, *(c->pvar)); // Mark actual object the global points to
// }
// }
// // TODO: what else to mark? gc_mark(
// // conservative mark?
// // weak refs?
// // finalize?
// return gc_sweep(h, sum_freed);
// // debug print free stats?
//}
// Mark globals as part of the tracing collector
// This is called by the collector thread
void gc_mark_globals()
{ {
#if GC_DEBUG_CONCISE_PRINTFS #if GC_DEBUG_CONCISE_PRINTFS
printf("(heap: %p size: %d)\n", h, (unsigned int)gc_heap_total_size(h)); printf("(gc_mark_globals heap: %p size: %d)\n", h, (unsigned int)gc_heap_total_size(h));
#endif #endif
// Mark global variables // Mark global variables
gc_mark(h, Cyc_global_variables); // Internal global used by the runtime gc_mark_black(Cyc_global_variables); // Internal global used by the runtime
// Marking it ensures all glos are marked // Marking it ensures all glos are marked
{ {
list l = global_table; list l = global_table;
for(; !nullp(l); l = cdr(l)){ for(; !nullp(l); l = cdr(l)){
cvar_type *c = (cvar_type *)car(l); cvar_type *c = (cvar_type *)car(l);
gc_mark(h, *(c->pvar)); // Mark actual object the global points to gc_mark_black(*(c->pvar)); // Mark actual object the global points to
} }
} }
// TODO: what else to mark? gc_mark(
// conservative mark?
// weak refs?
// finalize?
return gc_sweep(h, sum_freed);
// debug print free stats?
} }
// TODO: move globals to thread-specific structures.
// for example - gc_cont, gc_ans, gc_num_ans
char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown) { 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;
@ -2723,27 +2739,27 @@ void GC(void *data, closure cont, object *args, int num_args)
//fprintf(stdout, "DEBUG done minor GC, alloci = %d\n", alloci); //fprintf(stdout, "DEBUG done minor GC, alloci = %d\n", alloci);
// Check if we need to do a major GC // // Check if we need to do a major GC
if (heap_grown) { // if (heap_grown) {
size_t freed = 0, max_freed = 0; // size_t freed = 0, max_freed = 0;
#if GC_DEBUG_CONCISE_PRINTFS //#if GC_DEBUG_CONCISE_PRINTFS
time_t majorStart = time(NULL); // time_t majorStart = time(NULL);
fprintf(stdout, "DEBUG, starting major mark/sweep GC\n"); // JAE DEBUG // fprintf(stdout, "DEBUG, starting major mark/sweep GC\n"); // JAE DEBUG
#endif //#endif
gc_mark(Cyc_heap, cont); // gc_mark(Cyc_heap, cont);
for (i = 0; i < num_args; i++){ // for (i = 0; i < num_args; i++){
gc_mark(Cyc_heap, args[i]); // gc_mark(Cyc_heap, args[i]);
} // }
max_freed = gc_collect(Cyc_heap, &freed); // max_freed = gc_collect(Cyc_heap, &freed);
#if GC_DEBUG_CONCISE_PRINTFS //#if GC_DEBUG_CONCISE_PRINTFS
printf("done, freed = %d, max_freed = %d, elapsed = %ld\n", freed, max_freed, time(NULL) - majorStart); // printf("done, freed = %d, max_freed = %d, elapsed = %ld\n", freed, max_freed, time(NULL) - majorStart);
//JAE_DEBUG++; // //JAE_DEBUG++;
//if (JAE_DEBUG == 2) exit(1); // JAE DEBUG // //if (JAE_DEBUG == 2) exit(1); // JAE DEBUG
for (i = 0; i < 20; i++){ // for (i = 0; i < 20; i++){
printf("gcMoveCountsDEBUG[%d] = %d\n", i, gcMoveCountsDEBUG[i]); // printf("gcMoveCountsDEBUG[%d] = %d\n", i, gcMoveCountsDEBUG[i]);
} // }
#endif //#endif
} // }
/* Let it all go, Neo... */ /* Let it all go, Neo... */
longjmp(*(((gc_thread_data *)data)->jmp_start), 1); longjmp(*(((gc_thread_data *)data)->jmp_start), 1);