1717 generate_richcompare_wrapper ,
1818 generate_set_del_item_wrapper ,
1919)
20- from mypyc .common import NATIVE_PREFIX , PREFIX , REG_PREFIX , use_fastcall
20+ from mypyc .common import (
21+ ATTR_BITMAP_BITS ,
22+ ATTR_BITMAP_TYPE ,
23+ NATIVE_PREFIX ,
24+ PREFIX ,
25+ REG_PREFIX ,
26+ use_fastcall ,
27+ )
2128from mypyc .ir .class_ir import ClassIR , VTableEntries
2229from mypyc .ir .func_ir import FUNC_CLASSMETHOD , FUNC_STATICMETHOD , FuncDecl , FuncIR
23- from mypyc .ir .rtypes import RTuple , RType , object_rprimitive
30+ from mypyc .ir .rtypes import RTuple , RType , is_fixed_width_rtype , object_rprimitive
2431from mypyc .namegen import NameGenerator
2532from mypyc .sametype import is_same_type
2633
@@ -367,8 +374,17 @@ def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None:
367374 lines += ["typedef struct {" , "PyObject_HEAD" , "CPyVTableItem *vtable;" ]
368375 if cl .has_method ("__call__" ) and emitter .use_vectorcall ():
369376 lines .append ("vectorcallfunc vectorcall;" )
377+ bitmap_attrs = []
370378 for base in reversed (cl .base_mro ):
371379 if not base .is_trait :
380+ if base .bitmap_attrs :
381+ # Do we need another attribute bitmap field?
382+ if emitter .bitmap_field (len (base .bitmap_attrs ) - 1 ) not in bitmap_attrs :
383+ for i in range (0 , len (base .bitmap_attrs ), ATTR_BITMAP_BITS ):
384+ attr = emitter .bitmap_field (i )
385+ if attr not in bitmap_attrs :
386+ lines .append (f"{ ATTR_BITMAP_TYPE } { attr } ;" )
387+ bitmap_attrs .append (attr )
372388 for attr , rtype in base .attributes .items ():
373389 if (attr , rtype ) not in seen_attrs :
374390 lines .append (f"{ emitter .ctype_spaced (rtype )} { emitter .attr (attr )} ;" )
@@ -546,6 +562,9 @@ def generate_setup_for_class(
546562 emitter .emit_line ("}" )
547563 else :
548564 emitter .emit_line (f"self->vtable = { vtable_name } ;" )
565+ for i in range (0 , len (cl .bitmap_attrs ), ATTR_BITMAP_BITS ):
566+ field = emitter .bitmap_field (i )
567+ emitter .emit_line (f"self->{ field } = 0;" )
549568
550569 if cl .has_method ("__call__" ) and emitter .use_vectorcall ():
551570 name = cl .method_decl ("__call__" ).cname (emitter .names )
@@ -887,7 +906,7 @@ def generate_getter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> N
887906 always_defined = cl .is_always_defined (attr ) and not rtype .is_refcounted
888907
889908 if not always_defined :
890- emitter .emit_undefined_attr_check (rtype , attr_expr , "==" , unlikely = True )
909+ emitter .emit_undefined_attr_check (rtype , attr_expr , "==" , "self" , attr , cl , unlikely = True )
891910 emitter .emit_line ("PyErr_SetString(PyExc_AttributeError," )
892911 emitter .emit_line (f' "attribute { repr (attr )} of { repr (cl .name )} undefined");' )
893912 emitter .emit_line ("return NULL;" )
@@ -926,7 +945,7 @@ def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> N
926945 if rtype .is_refcounted :
927946 attr_expr = f"self->{ attr_field } "
928947 if not always_defined :
929- emitter .emit_undefined_attr_check (rtype , attr_expr , "!=" )
948+ emitter .emit_undefined_attr_check (rtype , attr_expr , "!=" , "self" , attr , cl )
930949 emitter .emit_dec_ref (f"self->{ attr_field } " , rtype )
931950 if not always_defined :
932951 emitter .emit_line ("}" )
@@ -943,9 +962,14 @@ def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> N
943962 emitter .emit_lines ("if (!tmp)" , " return -1;" )
944963 emitter .emit_inc_ref ("tmp" , rtype )
945964 emitter .emit_line (f"self->{ attr_field } = tmp;" )
965+ if is_fixed_width_rtype (rtype ) and not always_defined :
966+ emitter .emit_attr_bitmap_set ("tmp" , "self" , rtype , cl , attr )
967+
946968 if deletable :
947969 emitter .emit_line ("} else" )
948970 emitter .emit_line (f" self->{ attr_field } = { emitter .c_undefined_value (rtype )} ;" )
971+ if is_fixed_width_rtype (rtype ):
972+ emitter .emit_attr_bitmap_clear ("self" , rtype , cl , attr )
949973 emitter .emit_line ("return 0;" )
950974 emitter .emit_line ("}" )
951975
0 commit comments