py/objlist: Reduce code size in slice operations.

By refactoring the code to separate out the slicing operation from the
regular indexing operation, code can be shared between the various types of
slice operations (read/assign/delete).

Signed-off-by: Jeff Epler <jepler@gmail.com>
This commit is contained in:
Jeff Epler
2025-06-12 18:47:12 +02:00
committed by Damien George
parent 0ef5ede382
commit 73b1cbc17a

View File

@@ -159,56 +159,32 @@ 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)) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
mp_raise_NotImplementedError(NULL);
}
mp_int_t len_adj = slice.start - slice.stop;
assert(len_adj <= 0);
mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items /*NULL*/, 0, 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));
self->len += len_adj;
return mp_const_none;
}
#endif
mp_obj_t args[2] = {self_in, index};
list_pop(2, args);
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
bool fast = mp_seq_get_fast_slice_indexes(self->len, index, &slice);
if (value == MP_OBJ_SENTINEL) {
// load
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)) {
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
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)) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
// 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_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);
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
@@ -217,10 +193,10 @@ static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
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));
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_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));
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
@@ -229,6 +205,17 @@ static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
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 {
mp_obj_list_store(self_in, index, value);
return mp_const_none;
}