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:
parent
21441d78fd
commit
270b899ff0
1 changed files with 47 additions and 50 deletions
97
py/objlist.c
97
py/objlist.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue