Skip to content

Commit 3d59825

Browse files
committed
py: Cast mp_obj_t to concrete types explicitly.
mp_obj_t internal representation doesn't have to be a pointer to object, it can be anything. There's also a support for back-conversion in the form of MP_OBJ_UNCAST. This is kind of optimization/status quo preserver to minimize patching the existing code and avoid doing potentially expensive MP_OBJ_CAST over and over. But then one may imagine implementations where MP_OBJ_UNCAST is very expensive. But such implementations are unlikely interesting in practice.
1 parent ec1b1cf commit 3d59825

2 files changed

Lines changed: 57 additions & 39 deletions

File tree

py/obj.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
8989
#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2)
9090
#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
9191

92+
// Macros to convert between mp_obj_t and concrete object types.
93+
// These are identity operations in MicroPython, but ability to override
94+
// these operations are provided to experiment with other methods of
95+
// object representation and memory management.
96+
97+
// Cast mp_obj_t to object pointer
98+
#ifndef MP_OBJ_CAST
99+
#define MP_OBJ_CAST(o) ((void*)o)
100+
#endif
101+
102+
// Cast object pointer to mp_obj_t
103+
#ifndef MP_OBJ_UNCAST
104+
#define MP_OBJ_UNCAST(p) ((mp_obj_t)p)
105+
#endif
106+
92107
// These macros are used to declare and define constant function objects
93108
// You can put "static" in front of the definitions to make them local
94109

py/objlist.c

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "py/runtime.h"
3434
#include "py/stackctrl.h"
3535

36-
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, mp_uint_t cur);
36+
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur);
3737
STATIC mp_obj_list_t *list_new(mp_uint_t n);
3838
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
3939
STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
@@ -45,7 +45,7 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
4545
/* list */
4646

4747
STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
48-
mp_obj_list_t *o = o_in;
48+
mp_obj_list_t *o = MP_OBJ_CAST(o_in);
4949
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
5050
kind = PRINT_REPR;
5151
}
@@ -93,14 +93,14 @@ STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in)
9393
if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
9494
return false;
9595
}
96-
mp_obj_list_t *self = self_in;
97-
mp_obj_list_t *another = another_in;
96+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
97+
mp_obj_list_t *another = MP_OBJ_CAST(another_in);
9898

9999
return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
100100
}
101101

102102
STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
103-
mp_obj_list_t *self = self_in;
103+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
104104
switch (op) {
105105
case MP_UNARY_OP_BOOL: return MP_BOOL(self->len != 0);
106106
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
@@ -109,23 +109,23 @@ STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
109109
}
110110

111111
STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
112-
mp_obj_list_t *o = lhs;
112+
mp_obj_list_t *o = MP_OBJ_CAST(lhs);
113113
switch (op) {
114114
case MP_BINARY_OP_ADD: {
115115
if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
116116
return MP_OBJ_NULL; // op not supported
117117
}
118-
mp_obj_list_t *p = rhs;
118+
mp_obj_list_t *p = MP_OBJ_CAST(rhs);
119119
mp_obj_list_t *s = list_new(o->len + p->len);
120120
mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
121-
return s;
121+
return MP_OBJ_UNCAST(s);
122122
}
123123
case MP_BINARY_OP_INPLACE_ADD: {
124124
if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
125125
return MP_OBJ_NULL; // op not supported
126126
}
127127
list_extend(lhs, rhs);
128-
return o;
128+
return lhs;
129129
}
130130
case MP_BINARY_OP_MULTIPLY: {
131131
mp_int_t n;
@@ -137,7 +137,7 @@ STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
137137
}
138138
mp_obj_list_t *s = list_new(o->len * n);
139139
mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
140-
return s;
140+
return MP_OBJ_UNCAST(s);
141141
}
142142
case MP_BINARY_OP_EQUAL:
143143
case MP_BINARY_OP_LESS:
@@ -156,7 +156,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
156156
// delete
157157
#if MICROPY_PY_BUILTINS_SLICE
158158
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
159-
mp_obj_list_t *self = self_in;
159+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
160160
mp_bound_slice_t slice;
161161
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
162162
assert(0);
@@ -177,7 +177,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
177177
return mp_const_none;
178178
} else if (value == MP_OBJ_SENTINEL) {
179179
// load
180-
mp_obj_list_t *self = self_in;
180+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
181181
#if MICROPY_PY_BUILTINS_SLICE
182182
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
183183
mp_bound_slice_t slice;
@@ -186,17 +186,17 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
186186
}
187187
mp_obj_list_t *res = list_new(slice.stop - slice.start);
188188
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
189-
return res;
189+
return MP_OBJ_UNCAST(res);
190190
}
191191
#endif
192192
mp_uint_t index_val = mp_get_index(self->base.type, self->len, index, false);
193193
return self->items[index_val];
194194
} else {
195195
#if MICROPY_PY_BUILTINS_SLICE
196196
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
197-
mp_obj_list_t *self = self_in;
197+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
198198
assert(MP_OBJ_IS_TYPE(value, &mp_type_list));
199-
mp_obj_list_t *slice = value;
199+
mp_obj_list_t *slice = MP_OBJ_CAST(value);
200200
mp_bound_slice_t slice_out;
201201
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
202202
assert(0);
@@ -234,7 +234,7 @@ STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
234234

235235
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
236236
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
237-
mp_obj_list_t *self = self_in;
237+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
238238
if (self->len >= self->alloc) {
239239
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
240240
self->alloc *= 2;
@@ -247,8 +247,8 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
247247
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
248248
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
249249
if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
250-
mp_obj_list_t *self = self_in;
251-
mp_obj_list_t *arg = arg_in;
250+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
251+
mp_obj_list_t *arg = MP_OBJ_CAST(arg_in);
252252

253253
if (self->len + arg->len > self->alloc) {
254254
// TODO: use alloc policy for "4"
@@ -268,7 +268,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
268268
STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args) {
269269
assert(1 <= n_args && n_args <= 2);
270270
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
271-
mp_obj_list_t *self = args[0];
271+
mp_obj_list_t *self = MP_OBJ_CAST(args[0]);
272272
if (self->len == 0) {
273273
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
274274
}
@@ -324,8 +324,8 @@ mp_obj_t mp_obj_list_sort(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
324324
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
325325
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
326326

327-
mp_obj_list_t *self = pos_args[0];
328-
assert(MP_OBJ_IS_TYPE(self, &mp_type_list));
327+
assert(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));
328+
mp_obj_list_t *self = MP_OBJ_CAST(pos_args[0]);
329329

330330
if (self->len > 1) {
331331
mp_quicksort(self->items, self->items + self->len - 1,
@@ -338,7 +338,7 @@ mp_obj_t mp_obj_list_sort(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
338338

339339
STATIC mp_obj_t list_clear(mp_obj_t self_in) {
340340
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
341-
mp_obj_list_t *self = self_in;
341+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
342342
self->len = 0;
343343
self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);
344344
self->alloc = LIST_MIN_ALLOC;
@@ -348,26 +348,26 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) {
348348

349349
STATIC mp_obj_t list_copy(mp_obj_t self_in) {
350350
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
351-
mp_obj_list_t *self = self_in;
351+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
352352
return mp_obj_new_list(self->len, self->items);
353353
}
354354

355355
STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {
356356
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
357-
mp_obj_list_t *self = self_in;
357+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
358358
return mp_seq_count_obj(self->items, self->len, value);
359359
}
360360

361361
STATIC mp_obj_t list_index(mp_uint_t n_args, const mp_obj_t *args) {
362362
assert(2 <= n_args && n_args <= 4);
363363
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
364-
mp_obj_list_t *self = args[0];
364+
mp_obj_list_t *self = MP_OBJ_CAST(args[0]);
365365
return mp_seq_index_obj(self->items, self->len, n_args, args);
366366
}
367367

368368
STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
369369
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
370-
mp_obj_list_t *self = self_in;
370+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
371371
// insert has its own strange index logic
372372
mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx);
373373
if (index < 0) {
@@ -401,7 +401,7 @@ mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {
401401

402402
STATIC mp_obj_t list_reverse(mp_obj_t self_in) {
403403
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
404-
mp_obj_list_t *self = self_in;
404+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
405405

406406
mp_int_t len = self->len;
407407
for (mp_int_t i = 0; i < len/2; i++) {
@@ -462,7 +462,8 @@ void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
462462
}
463463

464464
STATIC mp_obj_list_t *list_new(mp_uint_t n) {
465-
mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
465+
mp_obj_t o_in = m_new_obj(mp_obj_list_t);
466+
mp_obj_list_t *o = MP_OBJ_CAST(o_in);
466467
mp_obj_list_init(o, n);
467468
return o;
468469
}
@@ -474,24 +475,24 @@ mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) {
474475
o->items[i] = items[i];
475476
}
476477
}
477-
return o;
478+
return MP_OBJ_UNCAST(o);
478479
}
479480

480481
void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
481-
mp_obj_list_t *self = self_in;
482+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
482483
*len = self->len;
483484
*items = self->items;
484485
}
485486

486487
void mp_obj_list_set_len(mp_obj_t self_in, mp_uint_t len) {
487488
// trust that the caller knows what it's doing
488489
// TODO realloc if len got much smaller than alloc
489-
mp_obj_list_t *self = self_in;
490+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
490491
self->len = len;
491492
}
492493

493494
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
494-
mp_obj_list_t *self = self_in;
495+
mp_obj_list_t *self = MP_OBJ_CAST(self_in);
495496
mp_uint_t i = mp_get_index(self->base.type, self->len, index, false);
496497
self->items[i] = value;
497498
}
@@ -501,14 +502,15 @@ void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
501502

502503
typedef struct _mp_obj_list_it_t {
503504
mp_obj_base_t base;
504-
mp_obj_list_t *list;
505+
mp_obj_t list;
505506
mp_uint_t cur;
506507
} mp_obj_list_it_t;
507508

508509
STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
509-
mp_obj_list_it_t *self = self_in;
510-
if (self->cur < self->list->len) {
511-
mp_obj_t o_out = self->list->items[self->cur];
510+
mp_obj_list_it_t *self = MP_OBJ_CAST(self_in);
511+
mp_obj_list_t *list = MP_OBJ_CAST(self->list);
512+
if (self->cur < list->len) {
513+
mp_obj_t o_out = list->items[self->cur];
512514
self->cur += 1;
513515
return o_out;
514516
} else {
@@ -523,10 +525,11 @@ STATIC const mp_obj_type_t mp_type_list_it = {
523525
.iternext = list_it_iternext,
524526
};
525527

526-
mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, mp_uint_t cur) {
527-
mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
528+
mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur) {
529+
mp_obj_t o_out = m_new_obj(mp_obj_list_it_t);
530+
mp_obj_list_it_t *o = MP_OBJ_CAST(o_out);
528531
o->base.type = &mp_type_list_it;
529532
o->list = list;
530533
o->cur = cur;
531-
return o;
534+
return o_out;
532535
}

0 commit comments

Comments
 (0)