Skip to content

Commit c2a823d

Browse files
committed
Initialize attribute default values + some refactoring
1 parent 4ad5e29 commit c2a823d

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

mypyc/codegen/emitclass.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ def generate_class_reuse(
193193
context = c_emitter.context
194194
name = cl.name_prefix(c_emitter.names) + "_free_instance"
195195
struct_name = cl.struct_name(c_emitter.names)
196-
context.declarations[name] = HeaderDeclaration(f"CPyThreadLocal {struct_name} *{name};", needs_export=True)
196+
context.declarations[name] = HeaderDeclaration(
197+
f"CPyThreadLocal {struct_name} *{name};", needs_export=True
198+
)
197199

198200

199201
def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None:
@@ -572,11 +574,14 @@ def generate_setup_for_class(
572574

573575
prefix = cl.name_prefix(emitter.names)
574576
if cl.reuse_freed_instance:
577+
# Attempt to use a per-type free list first (a free "list" with up to one object only).
575578
emitter.emit_line(f"if ({prefix}_free_instance != NULL) {{")
576579
emitter.emit_line(f"self = {prefix}_free_instance;")
577580
emitter.emit_line(f"{prefix}_free_instance = NULL;")
578581
emitter.emit_line("Py_SET_REFCNT(self, 1);")
579582
emitter.emit_line("PyObject_GC_Track(self);")
583+
if defaults_fn is not None:
584+
emit_attr_defaults_func_call(defaults_fn, "self", emitter)
580585
emitter.emit_line("return (PyObject *)self;")
581586
emitter.emit_line("}")
582587

@@ -593,9 +598,7 @@ def generate_setup_for_class(
593598
else:
594599
emitter.emit_line(f"self->vtable = {vtable_name};")
595600

596-
for i in range(0, len(cl.bitmap_attrs), BITMAP_BITS):
597-
field = emitter.bitmap_field(i)
598-
emitter.emit_line(f"self->{field} = 0;")
601+
emit_clear_bitmaps(cl, emitter)
599602

600603
if cl.has_method("__call__"):
601604
name = cl.method_decl("__call__").cname(emitter.names)
@@ -612,19 +615,34 @@ def generate_setup_for_class(
612615

613616
# Initialize attributes to default values, if necessary
614617
if defaults_fn is not None:
615-
emitter.emit_lines(
616-
"if ({}{}((PyObject *)self) == 0) {{".format(
617-
NATIVE_PREFIX, defaults_fn.cname(emitter.names)
618-
),
619-
"Py_DECREF(self);",
620-
"return NULL;",
621-
"}",
622-
)
618+
emit_attr_defaults_func_call(defaults_fn, "self", emitter)
623619

624620
emitter.emit_line("return (PyObject *)self;")
625621
emitter.emit_line("}")
626622

627623

624+
def emit_clear_bitmaps(cl: ClassIR, emitter: Emitter) -> None:
625+
"""Emit C code to clear bitmaps that track if attributes have an assigned value."""
626+
for i in range(0, len(cl.bitmap_attrs), BITMAP_BITS):
627+
field = emitter.bitmap_field(i)
628+
emitter.emit_line(f"self->{field} = 0;")
629+
630+
631+
def emit_attr_defaults_func_call(defaults_fn: FuncIR, self_name: str, emitter: Emitter) -> None:
632+
"""Emit C code to initialize attribute defaults by calling defaults_fn.
633+
634+
The code returns NULL on a raised exception.
635+
"""
636+
emitter.emit_lines(
637+
"if ({}{}((PyObject *){}) == 0) {{".format(
638+
NATIVE_PREFIX, defaults_fn.cname(emitter.names), self_name
639+
),
640+
"Py_DECREF(self);",
641+
"return NULL;",
642+
"}",
643+
)
644+
645+
628646
def generate_constructor_for_class(
629647
cl: ClassIR,
630648
fn: FuncDecl,
@@ -834,13 +852,6 @@ def emit_reuse_dealloc(cl: ClassIR, emitter: Emitter) -> None:
834852
emitter.emit_line("}")
835853

836854

837-
def emit_clear_bitmaps(cl: ClassIR, emitter: Emitter) -> None:
838-
"""Emit C code to clear bitmaps that track if attributes have an assigned value."""
839-
for i in range(0, len(cl.bitmap_attrs), BITMAP_BITS):
840-
field = emitter.bitmap_field(i)
841-
emitter.emit_line(f"self->{field} = 0;")
842-
843-
844855
def generate_finalize_for_class(
845856
del_method: FuncIR, finalize_func_name: str, emitter: Emitter
846857
) -> None:

0 commit comments

Comments
 (0)