@@ -587,17 +587,16 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
587587 }
588588 #if MICROPY_CPYTHON_COMPAT
589589 if (attr == MP_QSTR___dict__ ) {
590- // Create a new dict with a copy of the instance's map items.
590+ // Returns a read-only dict of the instance members.
591+ // If the internal locals is not fixed, a copy will be created.
591592 // This creates, unlike CPython, a 'read-only' __dict__: modifying
592593 // it will not result in modifications to the actual instance members.
593- mp_map_t * map = & self -> members ;
594- mp_obj_t attr_dict = mp_obj_new_dict (map -> used );
595- for (size_t i = 0 ; i < map -> alloc ; ++ i ) {
596- if (mp_map_slot_is_filled (map , i )) {
597- mp_obj_dict_store (attr_dict , map -> table [i ].key , map -> table [i ].value );
598- }
599- }
600- dest [0 ] = attr_dict ;
594+ mp_obj_dict_t dict ;
595+ dict .map = self -> members ;
596+ dict .base .type = & mp_type_dict ;
597+ dest [0 ] = mp_obj_dict_copy (MP_OBJ_FROM_PTR (dict ));
598+ dict = MP_OBJ_TO_PTR (dest [0 ]);
599+ dict -> map .is_fixed = 1 ;
601600 return ;
602601 }
603602 #endif
@@ -1015,7 +1014,16 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
10151014 }
10161015 #if MICROPY_CPYTHON_COMPAT
10171016 if (attr == MP_QSTR___dict__ ) {
1018- dest [0 ] = mp_obj_dict_copy (MP_OBJ_FROM_PTR (self -> locals_dict ));
1017+ // Returns a read-only dict of the class attributes.
1018+ // If the internal locals is not fixed, a copy will be created.
1019+ mp_obj_dict_t * dict = MP_OBJ_FROM_PTR (self -> locals_dict );
1020+ if (dict -> map .is_fixed ) {
1021+ dest [0 ] = dict ;
1022+ } else {
1023+ dest [0 ] = mp_obj_dict_copy (dict );
1024+ dict = MP_OBJ_TO_PTR (dest [0 ]);
1025+ dict -> map .is_fixed = 1 ;
1026+ }
10191027 return ;
10201028 }
10211029 #endif
0 commit comments