Skip to content

Commit 73b1cbc

Browse files
jeplerdpgeorge
authored andcommitted
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 <[email protected]>
1 parent 0ef5ede commit 73b1cbc

File tree

1 file changed

+44
-57
lines changed

1 file changed

+44
-57
lines changed

py/objlist.c

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -159,76 +159,63 @@ static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
159159
}
160160

161161
static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
162-
if (value == MP_OBJ_NULL) {
163-
// delete
164-
#if MICROPY_PY_BUILTINS_SLICE
165-
if (mp_obj_is_type(index, &mp_type_slice)) {
166-
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
167-
mp_bound_slice_t slice;
168-
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
169-
mp_raise_NotImplementedError(NULL);
162+
#if MICROPY_PY_BUILTINS_SLICE
163+
if (mp_obj_is_type(index, &mp_type_slice)) {
164+
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
165+
mp_bound_slice_t slice;
166+
bool fast = mp_seq_get_fast_slice_indexes(self->len, index, &slice);
167+
if (value == MP_OBJ_SENTINEL) {
168+
// load
169+
if (!fast) {
170+
return mp_seq_extract_slice(self->items, &slice);
170171
}
171-
172-
mp_int_t len_adj = slice.start - slice.stop;
173-
assert(len_adj <= 0);
174-
mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items /*NULL*/, 0, sizeof(*self->items));
172+
mp_obj_list_t *res = list_new(slice.stop - slice.start);
173+
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
174+
return MP_OBJ_FROM_PTR(res);
175+
}
176+
// assign/delete
177+
if (value == MP_OBJ_NULL) {
178+
// delete is equivalent to slice assignment of an empty sequence
179+
value = mp_const_empty_tuple;
180+
}
181+
if (!fast) {
182+
mp_raise_NotImplementedError(NULL);
183+
}
184+
size_t value_len;
185+
mp_obj_t *value_items;
186+
mp_obj_get_array(value, &value_len, &value_items);
187+
mp_int_t len_adj = value_len - (slice.stop - slice.start);
188+
if (len_adj > 0) {
189+
if (self->len + len_adj > self->alloc) {
190+
// TODO: Might optimize memory copies here by checking if block can
191+
// be grown inplace or not
192+
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
193+
self->alloc = self->len + len_adj;
194+
}
195+
mp_seq_replace_slice_grow_inplace(self->items, self->len,
196+
slice.start, slice.stop, value_items, value_len, len_adj, sizeof(*self->items));
197+
} else {
198+
mp_seq_replace_slice_no_grow(self->items, self->len,
199+
slice.start, slice.stop, value_items, value_len, sizeof(*self->items));
175200
// Clear "freed" elements at the end of list
176201
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
177-
self->len += len_adj;
178-
return mp_const_none;
202+
// TODO: apply allocation policy re: alloc_size
179203
}
180-
#endif
204+
self->len += len_adj;
205+
return mp_const_none;
206+
}
207+
#endif
208+
if (value == MP_OBJ_NULL) {
209+
// delete
181210
mp_obj_t args[2] = {self_in, index};
182211
list_pop(2, args);
183212
return mp_const_none;
184213
} else if (value == MP_OBJ_SENTINEL) {
185214
// load
186215
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
187-
#if MICROPY_PY_BUILTINS_SLICE
188-
if (mp_obj_is_type(index, &mp_type_slice)) {
189-
mp_bound_slice_t slice;
190-
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
191-
return mp_seq_extract_slice(self->items, &slice);
192-
}
193-
mp_obj_list_t *res = list_new(slice.stop - slice.start);
194-
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
195-
return MP_OBJ_FROM_PTR(res);
196-
}
197-
#endif
198216
size_t index_val = mp_get_index(self->base.type, self->len, index, false);
199217
return self->items[index_val];
200218
} else {
201-
#if MICROPY_PY_BUILTINS_SLICE
202-
if (mp_obj_is_type(index, &mp_type_slice)) {
203-
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
204-
size_t value_len;
205-
mp_obj_t *value_items;
206-
mp_obj_get_array(value, &value_len, &value_items);
207-
mp_bound_slice_t slice_out;
208-
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
209-
mp_raise_NotImplementedError(NULL);
210-
}
211-
mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
212-
if (len_adj > 0) {
213-
if (self->len + len_adj > self->alloc) {
214-
// TODO: Might optimize memory copies here by checking if block can
215-
// be grown inplace or not
216-
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
217-
self->alloc = self->len + len_adj;
218-
}
219-
mp_seq_replace_slice_grow_inplace(self->items, self->len,
220-
slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items));
221-
} else {
222-
mp_seq_replace_slice_no_grow(self->items, self->len,
223-
slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));
224-
// Clear "freed" elements at the end of list
225-
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
226-
// TODO: apply allocation policy re: alloc_size
227-
}
228-
self->len += len_adj;
229-
return mp_const_none;
230-
}
231-
#endif
232219
mp_obj_list_store(self_in, index, value);
233220
return mp_const_none;
234221
}

0 commit comments

Comments
 (0)