kopia lustrzana https://github.com/micropython/micropython
py/objtype: Optimise slot RAM usage for instance types.
In all cases other than where you have a native base with a protocol, it now fits into 4 GC blocks (like it did before the slots representation). Signed-off-by: Jim Mussared <jim.mussared@gmail.com>pull/9351/head
rodzic
cb0ffdd2bf
commit
165388e4eb
|
@ -72,6 +72,7 @@ typedef unsigned int uint;
|
||||||
#define m_new_obj(type) (m_new(type, 1))
|
#define m_new_obj(type) (m_new(type, 1))
|
||||||
#define m_new_obj_maybe(type) (m_new_maybe(type, 1))
|
#define m_new_obj_maybe(type) (m_new_maybe(type, 1))
|
||||||
#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type *)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))
|
#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type *)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))
|
||||||
|
#define m_new_obj_var0(obj_type, var_type, var_num) ((obj_type *)m_malloc0(sizeof(obj_type) + sizeof(var_type) * (var_num)))
|
||||||
#define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type *)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num)))
|
#define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type *)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num)))
|
||||||
#if MICROPY_ENABLE_FINALISER
|
#if MICROPY_ENABLE_FINALISER
|
||||||
#define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type))))
|
#define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type))))
|
||||||
|
|
|
@ -143,8 +143,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) {
|
mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) {
|
||||||
mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields);
|
mp_obj_namedtuple_type_t *o = m_new_obj_var0(mp_obj_namedtuple_type_t, qstr, n_fields);
|
||||||
memset(&o->base, 0, sizeof(o->base));
|
|
||||||
o->n_fields = n_fields;
|
o->n_fields = n_fields;
|
||||||
for (size_t i = 0; i < n_fields; i++) {
|
for (size_t i = 0; i < n_fields; i++) {
|
||||||
o->fields[i] = mp_obj_str_get_qstr(fields[i]);
|
o->fields[i] = mp_obj_str_get_qstr(fields[i]);
|
||||||
|
|
33
py/objtype.c
33
py/objtype.c
|
@ -1148,10 +1148,15 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a full-sized mp_obj_full_type_t instance (i.e. all slots / extended fields).
|
const void *base_protocol = NULL;
|
||||||
// Given that Python types use almost all the slots anyway, this doesn't cost anything
|
if (bases_len > 0) {
|
||||||
// extra.
|
base_protocol = MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol);
|
||||||
mp_obj_type_t *o = (mp_obj_type_t *)m_new0(mp_obj_full_type_t, 1);
|
}
|
||||||
|
|
||||||
|
// Allocate a variable-sized mp_obj_type_t with as many slots as we need
|
||||||
|
// (currently 9, plus 1 for base, plus 1 for base-protocol).
|
||||||
|
// Note: 11 slots pushes it from 4 to 5 GC blocks.
|
||||||
|
mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 9 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0));
|
||||||
o->base.type = &mp_type_type;
|
o->base.type = &mp_type_type;
|
||||||
o->flags = base_flags;
|
o->flags = base_flags;
|
||||||
o->name = name;
|
o->name = name;
|
||||||
|
@ -1166,13 +1171,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||||
// MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented)
|
// MP_OBJ_TYPE_SET_SLOT(o, iternext, not implemented)
|
||||||
MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7);
|
MP_OBJ_TYPE_SET_SLOT(o, buffer, instance_get_buffer, 7);
|
||||||
|
|
||||||
if (bases_len > 0) {
|
mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict);
|
||||||
// Inherit protocol from a base class. This allows to define an
|
MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 8);
|
||||||
// abstract base class which would translate C-level protocol to
|
|
||||||
// Python method calls, and any subclass inheriting from it will
|
|
||||||
// support this feature.
|
|
||||||
MP_OBJ_TYPE_SET_SLOT(o, protocol, MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0])), protocol), 8);
|
|
||||||
|
|
||||||
|
if (bases_len > 0) {
|
||||||
if (bases_len >= 2) {
|
if (bases_len >= 2) {
|
||||||
#if MICROPY_MULTIPLE_INHERITANCE
|
#if MICROPY_MULTIPLE_INHERITANCE
|
||||||
MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 9);
|
MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_tuple), 9);
|
||||||
|
@ -1182,10 +1184,15 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||||
} else {
|
} else {
|
||||||
MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 9);
|
MP_OBJ_TYPE_SET_SLOT(o, parent, MP_OBJ_TO_PTR(bases_items[0]), 9);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mp_obj_dict_t *locals_ptr = MP_OBJ_TO_PTR(locals_dict);
|
// Inherit protocol from a base class. This allows to define an
|
||||||
MP_OBJ_TYPE_SET_SLOT(o, locals_dict, locals_ptr, 10);
|
// abstract base class which would translate C-level protocol to
|
||||||
|
// Python method calls, and any subclass inheriting from it will
|
||||||
|
// support this feature.
|
||||||
|
if (base_protocol) {
|
||||||
|
MP_OBJ_TYPE_SET_SLOT(o, protocol, base_protocol, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_SPECIAL_ACCESSORS
|
#if ENABLE_SPECIAL_ACCESSORS
|
||||||
// Check if the class has any special accessor methods
|
// Check if the class has any special accessor methods
|
||||||
|
|
Ładowanie…
Reference in New Issue