Emit function that performs cycle GC traversal of an instance.
(cl: ClassIR, func_name: str, emitter: Emitter)
| 862 | |
| 863 | |
| 864 | def generate_traverse_for_class(cl: ClassIR, func_name: str, emitter: Emitter) -> None: |
| 865 | """Emit function that performs cycle GC traversal of an instance.""" |
| 866 | emitter.emit_line("static int") |
| 867 | emitter.emit_line( |
| 868 | f"{func_name}({cl.struct_name(emitter.names)} *self, visitproc visit, void *arg)" |
| 869 | ) |
| 870 | emitter.emit_line("{") |
| 871 | for base in reversed(cl.base_mro): |
| 872 | for attr, rtype in base.attributes.items(): |
| 873 | emitter.emit_gc_visit(f"self->{emitter.attr(attr)}", rtype) |
| 874 | base_args = "(PyObject *)self, visit, arg" |
| 875 | emitter.emit_line("int rv = 0;") |
| 876 | if cl.builtin_base: |
| 877 | emitter.emit_base_tp_function_call(cl, "tp_traverse", base_args, prefix="rv = ") |
| 878 | emitter.emit_line("if (rv != 0) return rv;") |
| 879 | if has_managed_dict(cl, emitter): |
| 880 | emitter.emit_line(f"rv = PyObject_VisitManagedDict({base_args});") |
| 881 | emitter.emit_line("if (rv != 0) return rv;") |
| 882 | elif cl.has_dict: |
| 883 | struct_name = cl.struct_name(emitter.names) |
| 884 | # __dict__ lives right after the struct and __weakref__ lives right after that |
| 885 | emitter.emit_gc_visit( |
| 886 | f"*((PyObject **)((char *)self + sizeof({struct_name})))", object_rprimitive |
| 887 | ) |
| 888 | emitter.emit_gc_visit( |
| 889 | f"*((PyObject **)((char *)self + sizeof(PyObject *) + sizeof({struct_name})))", |
| 890 | object_rprimitive, |
| 891 | ) |
| 892 | emitter.emit_line("return rv;") |
| 893 | emitter.emit_line("}") |
| 894 | |
| 895 | |
| 896 | def generate_clear_for_class(cl: ClassIR, func_name: str, emitter: Emitter) -> None: |
no test coverage detected
searching dependent graphs…