diff --git a/runtime.c b/runtime.c index 07e20fe9..494b9c35 100644 --- a/runtime.c +++ b/runtime.c @@ -2811,20 +2811,46 @@ object Cyc_bytevector_length(void *data, object bv) object Cyc_list2vector(void *data, object cont, object l) { object v = NULL; - object len; + object len_obj; object lst = l; - int i = 0; + int len, i = 0; + size_t element_vec_size; + make_c_opaque(opq, NULL); Cyc_check_pair_or_null(data, l); - len = Cyc_length(data, l); - v = alloca(sizeof(vector_type)); - ((vector) v)->hdr.mark = gc_color_red; - ((vector) v)->hdr.grayed = 0; - ((vector) v)->tag = vector_tag; - ((vector) v)->num_elements = obj_obj2int(len); - ((vector) v)->elements = - (((vector) v)->num_elements > 0) ? - (object *) alloca(sizeof(object) * ((vector) v)->num_elements) : NULL; + len_obj = Cyc_length(data, l); + len = obj_obj2int(len_obj); + element_vec_size = sizeof(object) * len; + if (element_vec_size >= MAX_STACK_OBJ) { + int heap_grown; + v = gc_alloc(((gc_thread_data *)data)->heap, + sizeof(vector_type) + element_vec_size, + boolean_f, // OK to populate manually over here + (gc_thread_data *)data, + &heap_grown); + ((vector) v)->hdr.mark = ((gc_thread_data *)data)->gc_alloc_color; + ((vector) v)->hdr.grayed = 0; + ((vector) v)->tag = vector_tag; + ((vector) v)->num_elements = len; + ((vector) v)->elements = (object *)(((char *)v) + sizeof(vector_type)); + // TODO: do we need to worry about stack object in the list???? + //// Use write barrier to ensure fill is moved to heap if it is on the stack + //// Otherwise if next minor GC misses fill it could be catastrophic + //car(&tmp_pair) = 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 { + v = alloca(sizeof(vector_type)); + ((vector) v)->hdr.mark = gc_color_red; + ((vector) v)->hdr.grayed = 0; + ((vector) v)->tag = vector_tag; + ((vector) v)->num_elements = len; + ((vector) v)->elements = + (((vector) v)->num_elements > 0) ? + (object *) alloca(element_vec_size) : NULL; + } while ((lst != NULL)) { ((vector) v)->elements[i++] = car(lst); lst = cdr(lst);