From 95cbe6b65ec84793f0f5ac2fd89c1375969a3bea Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 10 Jun 2020 10:46:38 +1000 Subject: [PATCH] py/objtype: Use mp_obj_dict_copy() for creating obj.__dict__ attribute. The resulting dict is now marked as read-only (is_fixed=1) to enforce the fact that changes to this dict will not be reflected in the class instance. This commit reduces code size by about 20 bytes, and should be more efficient because it creates a direct copy of the dict rather than reinserting all elements. --- py/objtype.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/py/objtype.c b/py/objtype.c index cb0fb267c8..a539fcab29 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -588,16 +588,13 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des #if MICROPY_CPYTHON_COMPAT if (attr == MP_QSTR___dict__) { // Create a new dict with a copy of the instance's map items. - // This creates, unlike CPython, a 'read-only' __dict__: modifying - // it will not result in modifications to the actual instance members. - mp_map_t *map = &self->members; - mp_obj_t attr_dict = mp_obj_new_dict(map->used); - for (size_t i = 0; i < map->alloc; ++i) { - if (mp_map_slot_is_filled(map, i)) { - mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value); - } - } - dest[0] = attr_dict; + // This creates, unlike CPython, a read-only __dict__ that can't be modified. + mp_obj_dict_t dict; + dict.base.type = &mp_type_dict; + dict.map = self->members; + dest[0] = mp_obj_dict_copy(MP_OBJ_FROM_PTR(&dict)); + mp_obj_dict_t *dest_dict = MP_OBJ_TO_PTR(dest[0]); + dest_dict->map.is_fixed = 1; return; } #endif