static jv* jvp_array_write(jv* a, int i) { assert(i >= 0); jvp_array* array = jvp_array_ptr(*a); int pos = i + jvp_array_offset(*a); if (pos < array->alloc_length && jvp_refcnt_unshared(a->u.ptr)) { // use existing array space for (int j = array->length; j <= pos; j++) { array->elements[j] = JV_NULL; } array->length = imax(pos + 1, array->length); a->size = imax(i + 1, a->size); return &array->elements[pos]; } else { // allocate a new array int new_length = imax(i + 1, jvp_array_length(*a)); jvp_array* new_array = jvp_array_alloc(ARRAY_SIZE_ROUND_UP(new_length)); int j; for (j = 0; j < jvp_array_length(*a); j++) { new_array->elements[j] = jv_copy(array->elements[j + jvp_array_offset(*a)]); } for (; j < new_length; j++) { new_array->elements[j] = JV_NULL; } new_array->length = new_length; jvp_array_free(*a); jv new_jv = {JV_KIND_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; *a = new_jv; return &new_array->elements[i]; } }
static jv* jvp_array_write(jv_nontrivial* a, int i) { assert(i >= 0); jvp_array* array = jvp_array_ptr(a); int pos = i + a->i[0]; if (pos < array->alloc_length) { // maybe we can update it in-place // FIXME: this "optimisation" can cause circular references #if 0 int can_write_past_end = array->length <= pos && /* the end of this array has never been used */ a->i[1] == array->length; /* the current slice sees the end of the array */ #endif int can_write_past_end = 0; if (can_write_past_end || jvp_refcnt_unshared(a)) { // extend the array for (int j = array->length; j <= pos; j++) { array->elements[j] = JV_NULL; } array->length = imax(pos + 1, array->length); a->i[1] = imax(pos + 1, a->i[1]); return &array->elements[pos]; } } int new_length = imax(i + 1, jvp_array_length(a)); jvp_array* new_array = jvp_array_alloc(ARRAY_SIZE_ROUND_UP(new_length)); int j; for (j = 0; j < jvp_array_length(a); j++) { new_array->elements[j] = jv_copy(array->elements[j + a->i[0]]); } for (; j < new_length; j++) { new_array->elements[j] = JV_NULL; } new_array->length = new_length; jvp_array_free(a); a->ptr = &new_array->refcnt; a->i[0] = 0; a->i[1] = new_length; return &new_array->elements[i]; }