@@ -229,6 +229,7 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None:
229229 name = cl .name
230230 name_prefix = cl .name_prefix (emitter .names )
231231
232+ allocate_name = emitter .native_function_name (cl .allocate )
232233 setup_name = emitter .native_function_name (cl .setup )
233234 new_name = f"{ name_prefix } _new"
234235 finalize_name = f"{ name_prefix } _finalize"
@@ -322,14 +323,15 @@ def emit_line() -> None:
322323 fields ["tp_basicsize" ] = base_size
323324
324325 if generate_full :
325- assert cl .setup is not None
326- emitter .emit_line (native_function_header (cl .setup , emitter ) + ";" )
327- assert cl .ctor is not None
328- emitter .emit_line (native_function_header (cl .ctor , emitter ) + ";" )
326+ for decl in [cl .allocate , cl .setup , cl .ctor ]:
327+ assert decl is not None
328+ emitter .emit_line (native_function_header (decl , emitter ) + ";" )
329329
330330 emit_line ()
331331 init_fn = cl .get_method ("__init__" )
332- generate_new_for_class (cl , new_name , vtable_name , setup_name , init_fn , emitter )
332+ generate_new_for_class (
333+ cl , new_name , vtable_name , allocate_name , setup_name , init_fn , emitter
334+ )
333335 emit_line ()
334336 generate_traverse_for_class (cl , traverse_name , emitter )
335337 emit_line ()
@@ -393,9 +395,13 @@ def emit_line() -> None:
393395
394396 emitter .emit_line ()
395397 if generate_full :
396- generate_setup_for_class (cl , defaults_fn , vtable_name , shadow_vtable_name , emitter )
398+ generate_allocate_for_class (cl , defaults_fn , emitter )
399+ emitter .emit_line ()
400+ generate_setup_for_class (cl , vtable_name , shadow_vtable_name , emitter )
397401 emitter .emit_line ()
398- generate_constructor_for_class (cl , cl .ctor , init_fn , setup_name , vtable_name , emitter )
402+ generate_constructor_for_class (
403+ cl , cl .ctor , init_fn , allocate_name , setup_name , vtable_name , emitter
404+ )
399405 emitter .emit_line ()
400406 if needs_getseters :
401407 generate_getseters (cl , emitter )
@@ -580,17 +586,11 @@ def generate_vtable(
580586 emitter .emit_line ("memcpy({name}, {name}_scratch, sizeof({name}));" .format (name = vtable_name ))
581587
582588
583- def generate_setup_for_class (
584- cl : ClassIR ,
585- defaults_fn : FuncIR | None ,
586- vtable_name : str ,
587- shadow_vtable_name : str | None ,
588- emitter : Emitter ,
589- ) -> None :
589+ def generate_allocate_for_class (cl : ClassIR , defaults_fn : FuncIR | None , emitter : Emitter ) -> None :
590590 """Generate a native function that allocates an instance of a class."""
591- emitter .emit_line (native_function_header (cl .setup , emitter ))
591+ emitter .emit_line (native_function_header (cl .allocate , emitter ))
592592 emitter .emit_line ("{" )
593- type_arg_name = REG_PREFIX + cl .setup .sig .args [0 ].name
593+ type_arg_name = REG_PREFIX + cl .allocate .sig .args [0 ].name
594594 emitter .emit_line (f"PyTypeObject *type = (PyTypeObject*){ type_arg_name } ;" )
595595 struct_name = cl .struct_name (emitter .names )
596596 emitter .emit_line (f"{ struct_name } *self;" )
@@ -609,24 +609,8 @@ def generate_setup_for_class(
609609 emitter .emit_line ("}" )
610610
611611 emitter .emit_line (f"self = ({ cl .struct_name (emitter .names )} *)type->tp_alloc(type, 0);" )
612- emitter .emit_line ("if (self == NULL)" )
613- emitter .emit_line (" return NULL;" )
614-
615- if shadow_vtable_name :
616- emitter .emit_line (f"if (type != { emitter .type_struct_name (cl )} ) {{" )
617- emitter .emit_line (f"self->vtable = { shadow_vtable_name } ;" )
618- emitter .emit_line ("} else {" )
619- emitter .emit_line (f"self->vtable = { vtable_name } ;" )
620- emitter .emit_line ("}" )
621- else :
622- emitter .emit_line (f"self->vtable = { vtable_name } ;" )
623-
624612 emit_clear_bitmaps (cl , emitter )
625613
626- if cl .has_method ("__call__" ):
627- name = cl .method_decl ("__call__" ).cname (emitter .names )
628- emitter .emit_line (f"self->vectorcall = { PREFIX } { name } ;" )
629-
630614 for base in reversed (cl .base_mro ):
631615 for attr , rtype in base .attributes .items ():
632616 value = emitter .c_undefined_value (rtype )
@@ -644,6 +628,34 @@ def generate_setup_for_class(
644628 emitter .emit_line ("}" )
645629
646630
631+ def generate_setup_for_class (
632+ cl : ClassIR , vtable_name : str , shadow_vtable_name : str | None , emitter : Emitter
633+ ) -> None :
634+ """Generate a native function that performs setup needed after allocation."""
635+ emitter .emit_line (native_function_header (cl .setup , emitter ))
636+ emitter .emit_line ("{" )
637+ obj_arg_name = REG_PREFIX + cl .setup .sig .args [0 ].name
638+ emitter .emit_line (f"PyTypeObject *type = Py_TYPE({ obj_arg_name } );" )
639+ struct_name = cl .struct_name (emitter .names )
640+ emitter .emit_line (f"{ struct_name } *self = ({ struct_name } *){ obj_arg_name } ;" )
641+
642+ if shadow_vtable_name :
643+ emitter .emit_line (f"if (type != { emitter .type_struct_name (cl )} ) {{" )
644+ emitter .emit_line (f"self->vtable = { shadow_vtable_name } ;" )
645+ emitter .emit_line ("} else {" )
646+ emitter .emit_line (f"self->vtable = { vtable_name } ;" )
647+ emitter .emit_line ("}" )
648+ else :
649+ emitter .emit_line (f"self->vtable = { vtable_name } ;" )
650+
651+ if cl .has_method ("__call__" ):
652+ name = cl .method_decl ("__call__" ).cname (emitter .names )
653+ emitter .emit_line (f"self->vectorcall = { PREFIX } { name } ;" )
654+
655+ emitter .emit_line ("return (PyObject *)self;" )
656+ emitter .emit_line ("}" )
657+
658+
647659def emit_clear_bitmaps (cl : ClassIR , emitter : Emitter ) -> None :
648660 """Emit C code to clear bitmaps that track if attributes have an assigned value."""
649661 for i in range (0 , len (cl .bitmap_attrs ), BITMAP_BITS ):
@@ -666,8 +678,9 @@ def emit_attr_defaults_func_call(defaults_fn: FuncIR, self_name: str, emitter: E
666678 )
667679
668680
669- def emit_setup_or_dunder_new_call (
681+ def emit_allocate_or_dunder_new_call (
670682 cl : ClassIR ,
683+ allocate_name : str ,
671684 setup_name : str ,
672685 type_arg : str ,
673686 native_prefix : bool ,
@@ -680,8 +693,9 @@ def emit_null_check() -> None:
680693
681694 new_fn = cl .get_method ("__new__" )
682695 if not new_fn :
683- emitter .emit_line (f"PyObject *self = { setup_name } ({ type_arg } );" )
696+ emitter .emit_line (f"PyObject *self = { allocate_name } ({ type_arg } );" )
684697 emit_null_check ()
698+ emitter .emit_line (f"self = { setup_name } (self);" )
685699 return
686700 prefix = emitter .get_group_prefix (new_fn .decl ) + NATIVE_PREFIX if native_prefix else PREFIX
687701 all_args = type_arg
@@ -694,11 +708,14 @@ def emit_null_check() -> None:
694708 emitter .emit_line (f"if (Py_TYPE(self) != { emitter .type_struct_name (cl )} )" )
695709 emitter .emit_line (" return self;" )
696710
711+ emitter .emit_line (f"self = { setup_name } (self);" )
712+
697713
698714def generate_constructor_for_class (
699715 cl : ClassIR ,
700716 fn : FuncDecl ,
701717 init_fn : FuncIR | None ,
718+ allocate_name : str ,
702719 setup_name : str ,
703720 vtable_name : str ,
704721 emitter : Emitter ,
@@ -717,7 +734,9 @@ def generate_constructor_for_class(
717734 and fn .sig .args [0 ].kind == ARG_STAR
718735 and fn .sig .args [1 ].kind == ARG_STAR2
719736 )
720- emit_setup_or_dunder_new_call (cl , setup_name , type_arg , not use_wrapper , new_args , emitter )
737+ emit_allocate_or_dunder_new_call (
738+ cl , allocate_name , setup_name , type_arg , not use_wrapper , new_args , emitter
739+ )
721740
722741 args = ", " .join (["self" ] + fn_args )
723742 if init_fn is not None :
@@ -779,6 +798,7 @@ def generate_new_for_class(
779798 cl : ClassIR ,
780799 func_name : str ,
781800 vtable_name : str ,
801+ allocate_name : str ,
782802 setup_name : str ,
783803 init_fn : FuncIR | None ,
784804 emitter : Emitter ,
@@ -797,7 +817,9 @@ def generate_new_for_class(
797817
798818 type_arg = "(PyObject*)type"
799819 new_args = "args, kwds"
800- emit_setup_or_dunder_new_call (cl , setup_name , type_arg , False , new_args , emitter )
820+ emit_allocate_or_dunder_new_call (
821+ cl , allocate_name , setup_name , type_arg , False , new_args , emitter
822+ )
801823 if (
802824 not init_fn
803825 or cl .allow_interpreted_subclasses
0 commit comments