@@ -587,17 +587,20 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
587
587
}
588
588
#if MICROPY_CPYTHON_COMPAT
589
589
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.
591
592
// This creates, unlike CPython, a 'read-only' __dict__: modifying
592
593
// 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
- }
594
+ mp_obj_t members_dict = mp_obj_new_dict (0 );
595
+ mp_obj_dict_t * dict = MP_OBJ_TO_PTR (members_dict );
596
+ dict -> map = self -> members ;
597
+ if (dict -> map .is_fixed ) {
598
+ dest [0 ] = dict ;
599
+ } else {
600
+ dest [0 ] = mp_obj_dict_copy (MP_OBJ_FROM_PTR (dict ));
601
+ dict = MP_OBJ_TO_PTR (dest [0 ]);
602
+ dict -> map .is_fixed = 1 ;
599
603
}
600
- dest [0 ] = attr_dict ;
601
604
return ;
602
605
}
603
606
#endif
@@ -1015,7 +1018,16 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
1015
1018
}
1016
1019
#if MICROPY_CPYTHON_COMPAT
1017
1020
if (attr == MP_QSTR___dict__ ) {
1018
- dest [0 ] = mp_obj_dict_copy (MP_OBJ_FROM_PTR (self -> locals_dict ));
1021
+ // Returns a read-only dict of the class attributes.
1022
+ // If the internal locals is not fixed, a copy will be created.
1023
+ mp_obj_dict_t * dict = MP_OBJ_FROM_PTR (self -> locals_dict );
1024
+ if (dict -> map .is_fixed ) {
1025
+ dest [0 ] = dict ;
1026
+ } else {
1027
+ dest [0 ] = mp_obj_dict_copy (dict );
1028
+ dict = MP_OBJ_TO_PTR (dest [0 ]);
1029
+ dict -> map .is_fixed = 1 ;
1030
+ }
1019
1031
return ;
1020
1032
}
1021
1033
#endif
0 commit comments