objlist: Reduce code size in slice operations.

By factoring out the all the slicing operations (as suggested
by @dpgeorge) into a single block, more code sharing can occur
and there is no need for a goto.

Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
Jeff Epler 2025-06-13 08:01:37 +02:00
parent 21441d78fd
commit 270b899ff0

View file

@ -159,66 +159,63 @@ static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (value == MP_OBJ_NULL) {
// delete
#if MICROPY_PY_BUILTINS_SLICE
if (mp_obj_is_type(index, &mp_type_slice)) {
value = mp_const_empty_tuple;
goto slice_assign;
}
#endif
mp_obj_t args[2] = {self_in, index};
list_pop(2, args);
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
// load
#if MICROPY_PY_BUILTINS_SLICE
if (mp_obj_is_type(index, &mp_type_slice)) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
#if MICROPY_PY_BUILTINS_SLICE
if (mp_obj_is_type(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
mp_bound_slice_t slice;
bool fast = mp_seq_get_fast_slice_indexes(self->len, index, &slice);
if (value == MP_OBJ_SENTINEL) {
// load
if (!fast) {
return mp_seq_extract_slice(self->items, &slice);
}
mp_obj_list_t *res = list_new(slice.stop - slice.start);
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
return MP_OBJ_FROM_PTR(res);
}
#endif
// assign/delete
if (value == MP_OBJ_NULL) {
// delete is equivalent to slice assignment of an empty sequence
value = mp_const_empty_tuple;
}
if (!fast) {
mp_raise_NotImplementedError(NULL);
}
size_t value_len;
mp_obj_t *value_items;
mp_obj_get_array(value, &value_len, &value_items);
mp_int_t len_adj = value_len - (slice.stop - slice.start);
if (len_adj > 0) {
if (self->len + len_adj > self->alloc) {
// TODO: Might optimize memory copies here by checking if block can
// be grown inplace or not
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
self->alloc = self->len + len_adj;
}
mp_seq_replace_slice_grow_inplace(self->items, self->len,
slice.start, slice.stop, value_items, value_len, len_adj, sizeof(*self->items));
} else {
mp_seq_replace_slice_no_grow(self->items, self->len,
slice.start, slice.stop, value_items, value_len, sizeof(*self->items));
// Clear "freed" elements at the end of list
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
// TODO: apply allocation policy re: alloc_size
}
self->len += len_adj;
return mp_const_none;
}
#endif
if (value == MP_OBJ_NULL) {
// delete
mp_obj_t args[2] = {self_in, index};
list_pop(2, args);
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
// load
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
size_t index_val = mp_get_index(self->base.type, self->len, index, false);
return self->items[index_val];
} else {
#if MICROPY_PY_BUILTINS_SLICE
if (mp_obj_is_type(index, &mp_type_slice)) {
slice_assign:;
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
size_t value_len;
mp_obj_t *value_items;
mp_obj_get_array(value, &value_len, &value_items);
mp_bound_slice_t slice_out;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
mp_raise_NotImplementedError(NULL);
}
mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
if (len_adj > 0) {
if (self->len + len_adj > self->alloc) {
// TODO: Might optimize memory copies here by checking if block can
// be grown inplace or not
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
self->alloc = self->len + len_adj;
}
mp_seq_replace_slice_grow_inplace(self->items, self->len,
slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items));
} else {
mp_seq_replace_slice_no_grow(self->items, self->len,
slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));
// Clear "freed" elements at the end of list
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
// TODO: apply allocation policy re: alloc_size
}
self->len += len_adj;
return mp_const_none;
}
#endif
mp_obj_list_store(self_in, index, value);
return mp_const_none;
}