diff options
author | Jim Mussared <jim.mussared@gmail.com> | 2022-04-22 13:05:56 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2022-09-19 19:06:04 +1000 |
commit | e8355eb16357b0bd234a9bcab1c9e8b72fcdbabc (patch) | |
tree | 894b411f743d6d285f0ed34c6685e9a33818b1cf /py | |
parent | 5ddf671944465411f90bd0968550b719d0dbdb80 (diff) | |
download | micropython-e8355eb16357b0bd234a9bcab1c9e8b72fcdbabc.tar.gz micropython-e8355eb16357b0bd234a9bcab1c9e8b72fcdbabc.zip |
py/obj: Add "full" and "empty" non-variable-length mp_obj_type_t.
This will always have the maximum/minimum size of a mp_obj_type_t
representation and can be used as a member in other structs.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'py')
-rw-r--r-- | py/obj.h | 15 | ||||
-rw-r--r-- | py/objnamedtuple.h | 5 | ||||
-rw-r--r-- | py/objtype.c | 5 |
3 files changed, 21 insertions, 4 deletions
@@ -562,6 +562,9 @@ typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); +// This struct will be updated to become a variable sized struct. In order to +// use this as a member, or allocate dynamically, use the mp_obj_empty_type_t +// or mp_obj_full_type_t structs below (which must be kept in sync). struct _mp_obj_type_t { // A type is an object so must start with this entry, which points to mp_type_type. mp_obj_base_t base; @@ -632,6 +635,13 @@ struct _mp_obj_type_t { struct _mp_obj_dict_t *locals_dict; }; +// Non-variable sized versions of mp_obj_type_t to be used as a member +// in other structs or for dynamic allocation. The fields are exactly +// as in mp_obj_type_t, but with a fixed size for the flexible array +// members. +typedef mp_obj_type_t mp_obj_empty_type_t; +typedef mp_obj_type_t mp_obj_full_type_t; + #define MP_TYPE_NULL_MAKE_NEW (NULL) // Implementation of MP_DEFINE_CONST_OBJ_TYPE for each number of arguments. @@ -657,14 +667,15 @@ struct _mp_obj_type_t { // of the 30th argument (30 is 13*2 + 4). #define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N -// This macro is used to define a object type in ROM. +// These macros are used to define a object type in ROM. // Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) -// It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* +// They use the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* // macro to use based on the number of arguments. It works by shifting the // numeric values 12, 11, ... 0 by the number of arguments, such that the // 30th argument ends up being the number to use. The _INV values are // placeholders because the slot arguments come in pairs. #define MP_DEFINE_CONST_OBJ_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_type_t, __VA_ARGS__)) +#define MP_DEFINE_CONST_OBJ_FULL_TYPE(...) MP_DEFINE_CONST_OBJ_TYPE_EXPAND(MP_DEFINE_CONST_OBJ_TYPE_NARGS(__VA_ARGS__, _INV, 12, _INV, 11, _INV, 10, _INV, 9, _INV, 8, _INV, 7, _INV, 6, _INV, 5, _INV, 4, _INV, 3, _INV, 2, _INV, 1, _INV, 0)(mp_obj_full_type_t, __VA_ARGS__)) // Constant types, globally accessible extern const mp_obj_type_t mp_type_type; diff --git a/py/objnamedtuple.h b/py/objnamedtuple.h index d32af35afe..9f23351d5a 100644 --- a/py/objnamedtuple.h +++ b/py/objnamedtuple.h @@ -29,7 +29,10 @@ #include "py/objtuple.h" typedef struct _mp_obj_namedtuple_type_t { - mp_obj_type_t base; + // Must use the full-size version to avoid this being a variable sized member. + // This means that named tuples use slightly more RAM than necessary, but + // no worse than if we didn't have slots/split representation. + mp_obj_full_type_t base; size_t n_fields; qstr fields[]; } mp_obj_namedtuple_type_t; diff --git a/py/objtype.c b/py/objtype.c index 77fe8e22e3..cc5a5e5802 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1148,7 +1148,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #endif } - mp_obj_type_t *o = m_new0(mp_obj_type_t, 1); + // Allocate a full-sized mp_obj_full_type_t instance (i.e. all slots / extended fields). + // Given that Python types use almost all the slots anyway, this doesn't cost anything + // extra. + mp_obj_type_t *o = (mp_obj_type_t *)m_new0(mp_obj_full_type_t, 1); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; |