Issue #214 - Prevent segfault with large vectors

Large vectors are allocated directly on the heap but may contain elements that are still on the stack. To ensure all of these elements are transported to the heap during the next minor GC, a special Opaque object is placed into the mutation table to ensure the whole vector is scanned for stack objects during the next minor GC.

Previously this was not done so objects from the "old" stack were still in memory and any changes to them were trashing random portions of the stack!
This commit is contained in:
Justin Ethier 2017-08-24 21:48:59 +00:00
parent f67b5fc1ea
commit 4be7d73e12

View file

@ -2253,6 +2253,7 @@ object Cyc_make_vector(void *data, object cont, int argc, object len, ...)
size_t element_vec_size; size_t element_vec_size;
va_list ap; va_list ap;
make_pair(tmp_pair, NULL, NULL); make_pair(tmp_pair, NULL, NULL);
make_c_opaque(opq, NULL);
va_start(ap, len); va_start(ap, len);
if (argc > 1) { if (argc > 1) {
fill = va_arg(ap, object); fill = va_arg(ap, object);
@ -2282,6 +2283,9 @@ object Cyc_make_vector(void *data, object cont, int argc, object len, ...)
// Otherwise if next minor GC misses fill it could be catastrophic // Otherwise if next minor GC misses fill it could be catastrophic
car(&tmp_pair) = fill; car(&tmp_pair) = fill;
add_mutation(data, &tmp_pair, -1, fill); add_mutation(data, &tmp_pair, -1, fill);
// Add a special object to indicate full vector must be scanned by GC
opaque_ptr(&opq) = v;
add_mutation(data, &opq, -1, v);
} else { } else {
v = alloca(sizeof(vector_type)); v = alloca(sizeof(vector_type));
((vector) v)->hdr.mark = gc_color_red; ((vector) v)->hdr.mark = gc_color_red;
@ -4841,6 +4845,13 @@ int gc_minor(void *data, object low_limit, object high_limit, closure cont,
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) {
// Already transported, skip // Already transported, skip
} else if (type_of(o) == c_opaque_tag) {
// Special case, pull out vector and inspect each element
vector_type *v = opaque_ptr(o);
int i;
for (i = 0; i < ((vector) v)->num_elements; i++) {
gc_move2heap(((vector) v)->elements[i]);
}
} else { } else {
printf("Unexpected type %d transporting mutation\n", type_of(o)); printf("Unexpected type %d transporting mutation\n", type_of(o));
exit(1); exit(1);