mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-13 15:57:36 +02:00
Copy objects into heap while we have the heap lock
Attempting to prevent issues with unitialized memory. Unfortunately this is not the primary cause of the errors.
This commit is contained in:
parent
173e1ca407
commit
8bf20a05b5
3 changed files with 183 additions and 98 deletions
163
gc.c
163
gc.c
|
@ -109,6 +109,159 @@ gc_heap *gc_heap_create(size_t size, size_t max_size, size_t chunk_size)
|
|||
return h;
|
||||
}
|
||||
|
||||
// Copy given object into given heap object
|
||||
char *gc_copy_obj(object dest, char *obj, gc_thread_data *thd)
|
||||
{
|
||||
// NOTE: no additional type checking because this is called from gc_move
|
||||
// which already does that
|
||||
|
||||
switch(type_of(obj)){
|
||||
case cons_tag: {
|
||||
list hp = dest;
|
||||
hp->hdr.mark = thd->gc_alloc_color;
|
||||
type_of(hp) = cons_tag;
|
||||
car(hp) = car(obj);
|
||||
cdr(hp) = cdr(obj);
|
||||
return (char *)hp;
|
||||
}
|
||||
case macro_tag: {
|
||||
macro_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = macro_tag;
|
||||
hp->fn = ((macro) obj)->fn;
|
||||
hp->num_args = ((macro) obj)->num_args;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure0_tag: {
|
||||
closure0_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure0_tag;
|
||||
hp->fn = ((closure0) obj)->fn;
|
||||
hp->num_args = ((closure0) obj)->num_args;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure1_tag: {
|
||||
closure1_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure1_tag;
|
||||
hp->fn = ((closure1) obj)->fn;
|
||||
hp->num_args = ((closure1) obj)->num_args;
|
||||
hp->elt1 = ((closure1) obj)->elt1;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure2_tag: {
|
||||
closure2_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure2_tag;
|
||||
hp->fn = ((closure2) obj)->fn;
|
||||
hp->num_args = ((closure2) obj)->num_args;
|
||||
hp->elt1 = ((closure2) obj)->elt1;
|
||||
hp->elt2 = ((closure2) obj)->elt2;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure3_tag: {
|
||||
closure3_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure3_tag;
|
||||
hp->fn = ((closure3) obj)->fn;
|
||||
hp->num_args = ((closure3) obj)->num_args;
|
||||
hp->elt1 = ((closure3) obj)->elt1;
|
||||
hp->elt2 = ((closure3) obj)->elt2;
|
||||
hp->elt3 = ((closure3) obj)->elt3;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure4_tag: {
|
||||
closure4_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure4_tag;
|
||||
hp->fn = ((closure4) obj)->fn;
|
||||
hp->num_args = ((closure4) obj)->num_args;
|
||||
hp->elt1 = ((closure4) obj)->elt1;
|
||||
hp->elt2 = ((closure4) obj)->elt2;
|
||||
hp->elt3 = ((closure4) obj)->elt3;
|
||||
hp->elt4 = ((closure4) obj)->elt4;
|
||||
return (char *)hp;
|
||||
}
|
||||
case closureN_tag: {
|
||||
int i;
|
||||
closureN_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closureN_tag;
|
||||
hp->fn = ((closureN) obj)->fn;
|
||||
hp->num_args = ((closureN) obj)->num_args;
|
||||
hp->num_elt = ((closureN) obj)-> num_elt;
|
||||
hp->elts = (object *)(((char *)hp) + sizeof(closureN_type));
|
||||
for (i = 0; i < hp->num_elt; i++) {
|
||||
hp->elts[i] = ((closureN) obj)->elts[i];
|
||||
}
|
||||
return (char *)hp;
|
||||
}
|
||||
case vector_tag: {
|
||||
int i;
|
||||
vector_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = vector_tag;
|
||||
hp->num_elt = ((vector) obj)-> num_elt;
|
||||
hp->elts = (object *)(((char *)hp) + sizeof(vector_type));
|
||||
for (i = 0; i < hp->num_elt; i++) {
|
||||
hp->elts[i] = ((vector) obj)->elts[i];
|
||||
}
|
||||
return (char *)hp;
|
||||
}
|
||||
case string_tag: {
|
||||
char *s;
|
||||
string_type *hp = dest;
|
||||
s = ((char *)hp) + sizeof(string_type);
|
||||
memcpy(s, string_str(obj), string_len(obj) + 1);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = string_tag;
|
||||
string_len(hp) = string_len(obj);
|
||||
string_str(hp) = s;
|
||||
return (char *)hp;
|
||||
}
|
||||
case integer_tag: {
|
||||
integer_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = integer_tag;
|
||||
hp->value = ((integer_type *) obj)->value;
|
||||
return (char *)hp;
|
||||
}
|
||||
case double_tag: {
|
||||
double_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = double_tag;
|
||||
hp->value = ((double_type *) obj)->value;
|
||||
return (char *)hp;
|
||||
}
|
||||
case port_tag: {
|
||||
port_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = port_tag;
|
||||
hp->fp = ((port_type *) obj)->fp;
|
||||
hp->mode = ((port_type *) obj)->mode;
|
||||
return (char *)hp;
|
||||
}
|
||||
case cvar_tag: {
|
||||
cvar_type *hp = dest;
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = cvar_tag;
|
||||
hp->pvar = ((cvar_type *) obj)->pvar;
|
||||
return (char *)hp;
|
||||
}
|
||||
case forward_tag:
|
||||
return (char *)forward(obj);
|
||||
case eof_tag:
|
||||
case primitive_tag:
|
||||
case boolean_tag:
|
||||
case symbol_tag:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "gc_copy_obj: bad tag obj=%p obj.tag=%ld\n",(object) obj, type_of(obj));
|
||||
exit(1);
|
||||
}
|
||||
return (char *)obj;
|
||||
}
|
||||
|
||||
int gc_grow_heap(gc_heap *h, size_t size, size_t chunk_size)
|
||||
{
|
||||
size_t cur_size, new_size;
|
||||
|
@ -125,7 +278,7 @@ printf("DEBUG - grew heap\n");
|
|||
return (h_new != NULL);
|
||||
}
|
||||
|
||||
void *gc_try_alloc(gc_heap *h, size_t size)
|
||||
void *gc_try_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd)
|
||||
{
|
||||
gc_free_list *f1, *f2, *f3;
|
||||
pthread_mutex_lock(&heap_lock);
|
||||
|
@ -143,6 +296,8 @@ void *gc_try_alloc(gc_heap *h, size_t size)
|
|||
} else { /* Take the whole chunk */
|
||||
f1->next = f2->next;
|
||||
}
|
||||
// Copy object into heap now to avoid any uninitialized memory issues
|
||||
gc_copy_obj(f2, obj, thd);
|
||||
pthread_mutex_unlock(&heap_lock);
|
||||
return f2;
|
||||
}
|
||||
|
@ -157,7 +312,7 @@ void *gc_try_alloc(gc_heap *h, size_t size)
|
|||
// maybe only lock during each individual operation, not for a whole
|
||||
// sweep or alloc
|
||||
|
||||
void *gc_alloc(gc_heap *h, size_t size, int *heap_grown)
|
||||
void *gc_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd, int *heap_grown)
|
||||
{
|
||||
void *result = NULL;
|
||||
size_t max_freed = 0, sum_freed = 0, total_size;
|
||||
|
@ -166,7 +321,7 @@ void *gc_alloc(gc_heap *h, size_t size, int *heap_grown)
|
|||
// the allowed ratio, try growing heap.
|
||||
// then try realloc. if cannot alloc now, then throw out of memory error
|
||||
size = gc_heap_align(size);
|
||||
result = gc_try_alloc(h, size);
|
||||
result = gc_try_alloc(h, size, obj, thd);
|
||||
if (!result) {
|
||||
// TODO: may want to consider not doing this now, and implementing gc_collect as
|
||||
// part of the runtime, since we would have all of the roots, stack args,
|
||||
|
@ -181,7 +336,7 @@ void *gc_alloc(gc_heap *h, size_t size, int *heap_grown)
|
|||
gc_grow_heap(h, size, 0);
|
||||
*heap_grown = 1;
|
||||
// }
|
||||
result = gc_try_alloc(h, size);
|
||||
result = gc_try_alloc(h, size, obj, thd);
|
||||
if (!result) {
|
||||
fprintf(stderr, "out of memory error allocating %d bytes\n", size);
|
||||
exit(1); // TODO: throw error???
|
||||
|
|
|
@ -129,8 +129,9 @@ void gc_initialize();
|
|||
void gc_add_mutator(gc_thread_data *thd);
|
||||
gc_heap *gc_heap_create(size_t size, size_t max_size, size_t chunk_size);
|
||||
int gc_grow_heap(gc_heap *h, size_t size, size_t chunk_size);
|
||||
void *gc_try_alloc(gc_heap *h, size_t size);
|
||||
void *gc_alloc(gc_heap *h, size_t size, int *heap_grown);
|
||||
char *gc_copy_obj(object hp, char *obj, gc_thread_data *thd);
|
||||
void *gc_try_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd);
|
||||
void *gc_alloc(gc_heap *h, size_t size, char *obj, gc_thread_data *thd, int *heap_grown);
|
||||
size_t gc_allocated_bytes(object obj);
|
||||
gc_heap *gc_heap_last(gc_heap *h);
|
||||
size_t gc_heap_total_size(gc_heap *h);
|
||||
|
|
113
runtime.c
113
runtime.c
|
@ -2456,16 +2456,17 @@ void gc_mark_globals()
|
|||
char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown) {
|
||||
if (!is_object_type(obj)) return obj;
|
||||
|
||||
//gcMoveCountsDEBUG[type_of(obj)]++;
|
||||
|
||||
// !!!
|
||||
// TODO: clean up code below and consolidate with gc_copy_obj in gc.c:
|
||||
// !!!
|
||||
|
||||
|
||||
//gcMoveCountsDEBUG[type_of(obj)]++;
|
||||
//printf("DEBUG gc_move type = %ld\n", type_of(obj)); // JAE DEBUG
|
||||
switch(type_of(obj)){
|
||||
case cons_tag: {
|
||||
list hp = gc_alloc(Cyc_heap, sizeof(cons_type), heap_grown); // hp ==> new heap object
|
||||
hp->hdr.mark = thd->gc_alloc_color;
|
||||
type_of(hp) = cons_tag;
|
||||
car(hp) = car(obj);
|
||||
cdr(hp) = cdr(obj);
|
||||
list hp = gc_alloc(Cyc_heap, sizeof(cons_type), obj, thd, heap_grown); // hp ==> new heap object
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
// keep track of each allocation so we can scan/move
|
||||
|
@ -2474,169 +2475,97 @@ char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown) {
|
|||
return (char *)hp;
|
||||
}
|
||||
case macro_tag: {
|
||||
macro_type *hp = gc_alloc(Cyc_heap, sizeof(macro_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = macro_tag;
|
||||
hp->fn = ((macro) obj)->fn;
|
||||
hp->num_args = ((macro) obj)->num_args;
|
||||
macro_type *hp = gc_alloc(Cyc_heap, sizeof(macro_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure0_tag: {
|
||||
closure0_type *hp = gc_alloc(Cyc_heap, sizeof(closure0_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure0_tag;
|
||||
hp->fn = ((closure0) obj)->fn;
|
||||
hp->num_args = ((closure0) obj)->num_args;
|
||||
closure0_type *hp = gc_alloc(Cyc_heap, sizeof(closure0_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure1_tag: {
|
||||
closure1_type *hp = gc_alloc(Cyc_heap, sizeof(closure1_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure1_tag;
|
||||
hp->fn = ((closure1) obj)->fn;
|
||||
hp->num_args = ((closure1) obj)->num_args;
|
||||
hp->elt1 = ((closure1) obj)->elt1;
|
||||
closure1_type *hp = gc_alloc(Cyc_heap, sizeof(closure1_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure2_tag: {
|
||||
closure2_type *hp = gc_alloc(Cyc_heap, sizeof(closure2_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure2_tag;
|
||||
hp->fn = ((closure2) obj)->fn;
|
||||
hp->num_args = ((closure2) obj)->num_args;
|
||||
hp->elt1 = ((closure2) obj)->elt1;
|
||||
hp->elt2 = ((closure2) obj)->elt2;
|
||||
closure2_type *hp = gc_alloc(Cyc_heap, sizeof(closure2_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure3_tag: {
|
||||
closure3_type *hp = gc_alloc(Cyc_heap, sizeof(closure3_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure3_tag;
|
||||
hp->fn = ((closure3) obj)->fn;
|
||||
hp->num_args = ((closure3) obj)->num_args;
|
||||
hp->elt1 = ((closure3) obj)->elt1;
|
||||
hp->elt2 = ((closure3) obj)->elt2;
|
||||
hp->elt3 = ((closure3) obj)->elt3;
|
||||
closure3_type *hp = gc_alloc(Cyc_heap, sizeof(closure3_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closure4_tag: {
|
||||
closure4_type *hp = gc_alloc(Cyc_heap, sizeof(closure4_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closure4_tag;
|
||||
hp->fn = ((closure4) obj)->fn;
|
||||
hp->num_args = ((closure4) obj)->num_args;
|
||||
hp->elt1 = ((closure4) obj)->elt1;
|
||||
hp->elt2 = ((closure4) obj)->elt2;
|
||||
hp->elt3 = ((closure4) obj)->elt3;
|
||||
hp->elt4 = ((closure4) obj)->elt4;
|
||||
closure4_type *hp = gc_alloc(Cyc_heap, sizeof(closure4_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case closureN_tag: {
|
||||
int i;
|
||||
closureN_type *hp = gc_alloc(Cyc_heap,
|
||||
sizeof(closureN_type) + sizeof(object) * (((closureN) obj)->num_elt),
|
||||
heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = closureN_tag;
|
||||
hp->fn = ((closureN) obj)->fn;
|
||||
hp->num_args = ((closureN) obj)->num_args;
|
||||
hp->num_elt = ((closureN) obj)-> num_elt;
|
||||
hp->elts = (object *)(((char *)hp) + sizeof(closureN_type));
|
||||
for (i = 0; i < hp->num_elt; i++) {
|
||||
hp->elts[i] = ((closureN) obj)->elts[i];
|
||||
}
|
||||
obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case vector_tag: {
|
||||
int i;
|
||||
vector_type *hp = gc_alloc(Cyc_heap,
|
||||
sizeof(vector_type) + sizeof(object) * (((vector) obj)->num_elt),
|
||||
heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = vector_tag;
|
||||
hp->num_elt = ((vector) obj)-> num_elt;
|
||||
hp->elts = (object *)(((char *)hp) + sizeof(vector_type));
|
||||
for (i = 0; i < hp->num_elt; i++) {
|
||||
hp->elts[i] = ((vector) obj)->elts[i];
|
||||
}
|
||||
obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case string_tag: {
|
||||
char *s;
|
||||
string_type *hp = gc_alloc(Cyc_heap,
|
||||
sizeof(string_type) + ((string_len(obj) + 1)),
|
||||
heap_grown);
|
||||
s = ((char *)hp) + sizeof(string_type);
|
||||
memcpy(s, string_str(obj), string_len(obj) + 1);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = string_tag;
|
||||
string_len(hp) = string_len(obj);
|
||||
string_str(hp) = s;
|
||||
obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case integer_tag: {
|
||||
integer_type *hp = gc_alloc(Cyc_heap, sizeof(integer_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = integer_tag;
|
||||
hp->value = ((integer_type *) obj)->value;
|
||||
integer_type *hp = gc_alloc(Cyc_heap, sizeof(integer_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case double_tag: {
|
||||
double_type *hp = gc_alloc(Cyc_heap, sizeof(double_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = double_tag;
|
||||
hp->value = ((double_type *) obj)->value;
|
||||
double_type *hp = gc_alloc(Cyc_heap, sizeof(double_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case port_tag: {
|
||||
port_type *hp = gc_alloc(Cyc_heap, sizeof(port_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = port_tag;
|
||||
hp->fp = ((port_type *) obj)->fp;
|
||||
hp->mode = ((port_type *) obj)->mode;
|
||||
port_type *hp = gc_alloc(Cyc_heap, sizeof(port_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
return (char *)hp;
|
||||
}
|
||||
case cvar_tag: {
|
||||
cvar_type *hp = gc_alloc(Cyc_heap, sizeof(cvar_type), heap_grown);
|
||||
mark(hp) = thd->gc_alloc_color;
|
||||
type_of(hp) = cvar_tag;
|
||||
hp->pvar = ((cvar_type *) obj)->pvar;
|
||||
cvar_type *hp = gc_alloc(Cyc_heap, sizeof(cvar_type), obj, thd, heap_grown);
|
||||
forward(obj) = hp;
|
||||
type_of(obj) = forward_tag;
|
||||
gc_thr_add_to_move_buffer(thd, alloci, hp);
|
||||
|
@ -2649,7 +2578,7 @@ char *gc_move(char *obj, gc_thread_data *thd, int *alloci, int *heap_grown) {
|
|||
case boolean_tag: break;
|
||||
case symbol_tag: break; // JAE TODO: raise an error here? Should not be possible in real code, though (IE, without GC DEBUG flag)
|
||||
default:
|
||||
fprintf(stderr, "gc_move: bad tag x=%p x.tag=%ld\n",(object) obj, type_of(obj));
|
||||
fprintf(stderr, "gc_move: bad tag obj=%p obj.tag=%ld\n",(object) obj, type_of(obj));
|
||||
exit(1);
|
||||
}
|
||||
return (char *)obj;
|
||||
|
|
Loading…
Add table
Reference in a new issue