Change how mutations are stored in memory

Use a reallocated memory buffer instead of malloc'd pairs. This should speed things up by reducing the number of allocations and by keeping mutations in contiguous sections of memory.
This commit is contained in:
Justin Ethier 2016-07-15 23:14:36 -04:00
parent 9e2a51fdae
commit 1c0c0bb315
3 changed files with 40 additions and 42 deletions

27
gc.c
View file

@ -831,27 +831,6 @@ void gc_thr_add_to_move_buffer(gc_thread_data * d, int *alloci, object obj)
(*alloci)++; (*alloci)++;
} }
// Generic buffer functions
void **vpbuffer_realloc(void **buf, int *len)
{
return realloc(buf, (*len) * sizeof(void *));
}
void **vpbuffer_add(void **buf, int *len, int i, void *obj)
{
if (i == *len) {
*len *= 2;
buf = vpbuffer_realloc(buf, len);
}
buf[i] = obj;
return buf;
}
void vpbuffer_free(void **buf)
{
free(buf);
}
// END heap definitions // END heap definitions
// Tri-color GC section // Tri-color GC section
@ -1458,6 +1437,10 @@ void gc_thread_data_init(gc_thread_data * thd, int mut_num, char *stack_base,
thd->stack_trace_idx = 0; thd->stack_trace_idx = 0;
thd->stack_prev_frame = NULL; thd->stack_prev_frame = NULL;
thd->mutations = NULL; thd->mutations = NULL;
thd->mutation_buflen = 128;
thd->mutation_count = 0;
thd->mutations =
vpbuffer_realloc(thd->mutations, &(thd->mutation_buflen));
thd->exception_handler_stack = NULL; thd->exception_handler_stack = NULL;
// thd->thread = NULL; // thd->thread = NULL;
thd->thread_state = CYC_THREAD_STATE_NEW; thd->thread_state = CYC_THREAD_STATE_NEW;
@ -1503,7 +1486,7 @@ void gc_thread_data_free(gc_thread_data * thd)
if (thd->stack_traces) if (thd->stack_traces)
free(thd->stack_traces); free(thd->stack_traces);
if (thd->mutations) { if (thd->mutations) {
clear_mutations(thd); free(thd->mutations);
} }
free(thd); free(thd);
} }

View file

@ -118,7 +118,9 @@ struct gc_thread_data_t {
char *stack_start; char *stack_start;
char *stack_limit; char *stack_limit;
// Minor GC write barrier // Minor GC write barrier
void *mutations; void **mutations;
int mutation_buflen;
int mutation_count;
// List of objects moved to heap during minor GC // List of objects moved to heap during minor GC
void **moveBuf; void **moveBuf;
int moveBufLen; int moveBufLen;

View file

@ -357,33 +357,26 @@ void debug_dump_globals()
* Note these functions and underlying data structure are only used by * Note these functions and underlying data structure are only used by
* the calling thread, so locking is not required. * the calling thread, so locking is not required.
*/ */
void add_mutation(void *data, object var, int index, object value) void add_mutation(void *data, object var, int index, object value)
{ {
gc_thread_data *thd = (gc_thread_data *) data; gc_thread_data *thd = (gc_thread_data *) data;
if (is_object_type(value)) { if (is_object_type(value)) {
thd->mutations = vpbuffer_add(thd->mutations, &(thd->mutation_buflen), thd->mutation_count, var);
thd->mutation_count++;
if (index >= 0) { if (index >= 0) {
// For vectors only, malloc_make_pair index as another var. That way // For vectors only, add index as another var. That way
// the write barrier only needs to inspect the mutated index. // the write barrier only needs to inspect the mutated index.
thd->mutations = malloc_make_pair(obj_int2obj(index), thd->mutations); thd->mutations = vpbuffer_add(thd->mutations, &(thd->mutation_buflen), thd->mutation_count, obj_int2obj(index));
thd->mutation_count++;
} }
thd->mutations = malloc_make_pair(var, thd->mutations);
} }
} }
/* TODO: consider a more efficient implementation, such as reusing old nodes
instead of reclaiming them each time
*/
void clear_mutations(void *data) void clear_mutations(void *data)
{ {
// Not clearing memory, just resetting count
gc_thread_data *thd = (gc_thread_data *) data; gc_thread_data *thd = (gc_thread_data *) data;
list l = thd->mutations, next; thd->mutation_count = 0;
while (l != NULL) {
next = cdr(l);
free(l);
l = next;
}
thd->mutations = NULL;
} }
/* END mutation table */ /* END mutation table */
@ -3791,9 +3784,9 @@ int gc_minor(void *data, object low_limit, object high_limit, closure cont,
// Transport mutations // Transport mutations
{ {
list l; int l = 0;
for (l = ((gc_thread_data *) data)->mutations; l != NULL; l = cdr(l)) { while (l < ((gc_thread_data *) data)->mutation_count) {
object o = car(l); object o = ((gc_thread_data *) data)->mutations[l++]; //car(l);
if (is_value_type(o)) { if (is_value_type(o)) {
// Can happen if a vector element was already // Can happen if a vector element was already
// moved and we found an index. Just ignore it // moved and we found an index. Just ignore it
@ -3804,8 +3797,7 @@ int gc_minor(void *data, object low_limit, object high_limit, closure cont,
int i; int i;
object idx; object idx;
// For vectors, index is encoded as the next mutation // For vectors, index is encoded as the next mutation
l = cdr(l); idx = ((gc_thread_data *) data)->mutations[l++];
idx = car(l);
i = obj_obj2int(idx); i = obj_obj2int(idx);
gc_move2heap(((vector) o)->elements[i]); gc_move2heap(((vector) o)->elements[i]);
} else if (type_of(o) == forward_tag) { } else if (type_of(o) == forward_tag) {
@ -4446,6 +4438,27 @@ object copy2heap(void *data, object obj)
&on_stack); &on_stack);
} }
// Generic buffer functions
void **vpbuffer_realloc(void **buf, int *len)
{
return realloc(buf, (*len) * sizeof(void *));
}
void **vpbuffer_add(void **buf, int *len, int i, void *obj)
{
if (i == *len) {
*len *= 2;
buf = vpbuffer_realloc(buf, len);
}
buf[i] = obj;
return buf;
}
void vpbuffer_free(void **buf)
{
free(buf);
}
/* RNG section */ /* RNG section */
#define norm 2.328306549295728e-10 #define norm 2.328306549295728e-10
#define m1 4294967087.0 #define m1 4294967087.0