diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs index ab4a7af0a..9ac1adc0f 100644 --- a/src/runtime/constructorbinding.cs +++ b/src/runtime/constructorbinding.cs @@ -149,17 +149,10 @@ public static IntPtr tp_repr(IntPtr ob) return self.repr; } - protected override void Dealloc() + protected override void Clear() { Runtime.Py_CLEAR(ref this.repr); - base.Dealloc(); - } - - public static int tp_clear(IntPtr ob) - { - var self = (ConstructorBinding)GetManagedObject(ob); - Runtime.Py_CLEAR(ref self.repr); - return 0; + base.Clear(); } public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg) @@ -248,17 +241,10 @@ public static IntPtr tp_repr(IntPtr ob) return self.repr; } - protected override void Dealloc() + protected override void Clear() { Runtime.Py_CLEAR(ref this.repr); - base.Dealloc(); - } - - public static int tp_clear(IntPtr ob) - { - var self = (BoundContructor)GetManagedObject(ob); - Runtime.Py_CLEAR(ref self.repr); - return 0; + base.Clear(); } public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg) diff --git a/src/runtime/eventbinding.cs b/src/runtime/eventbinding.cs index 60b9bba92..65c8fdccf 100644 --- a/src/runtime/eventbinding.cs +++ b/src/runtime/eventbinding.cs @@ -103,17 +103,10 @@ public static IntPtr tp_repr(IntPtr ob) return Runtime.PyString_FromString(s); } - protected override void Dealloc() + protected override void Clear() { Runtime.Py_CLEAR(ref this.target); - base.Dealloc(); - } - - public static int tp_clear(IntPtr ob) - { - var self = (EventBinding)GetManagedObject(ob); - Runtime.Py_CLEAR(ref self.target); - return 0; + base.Clear(); } } } diff --git a/src/runtime/eventobject.cs b/src/runtime/eventobject.cs index e9bd98821..941bbdf46 100644 --- a/src/runtime/eventobject.cs +++ b/src/runtime/eventobject.cs @@ -198,14 +198,14 @@ public static IntPtr tp_repr(IntPtr ob) } - protected override void Dealloc() + protected override void Clear() { if (this.unbound is not null) { Runtime.XDecref(this.unbound.pyHandle); this.unbound = null; } - base.Dealloc(); + base.Clear(); } } diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index db9eb0f72..78df805ee 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -56,10 +56,21 @@ void SetupGc () protected virtual void Dealloc() { - ClearObjectDict(this.pyHandle); + var type = Runtime.PyObject_TYPE(this.ObjectReference); Runtime.PyObject_GC_Del(this.pyHandle); - // Not necessary for decref of `tpHandle`. + // Not necessary for decref of `tpHandle` - it is borrowed + this.FreeGCHandle(); + + // we must decref our type: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dealloc + Runtime.XDecref(type.DangerousGetAddress()); + } + + /// DecRefs and nulls any fields pointing back to Python + protected virtual void Clear() + { + ClearObjectDict(this.pyHandle); + // Not necessary for decref of `tpHandle` - it is borrowed } /// @@ -88,17 +99,22 @@ public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) } - /// - /// Default dealloc implementation. - /// public static void tp_dealloc(IntPtr ob) { // Clean up a Python instance of this extension type. This // frees the allocated Python object and decrefs the type. var self = (ExtensionType)GetManagedObject(ob); + self?.Clear(); self?.Dealloc(); } + public static int tp_clear(IntPtr ob) + { + var self = (ExtensionType)GetManagedObject(ob); + self?.Clear(); + return 0; + } + protected override void OnLoad(InterDomainContext context) { base.OnLoad(context); diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index 783717189..c1e729f9e 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -229,23 +229,11 @@ public static IntPtr tp_repr(IntPtr ob) return Runtime.PyString_FromString($"<{type} method '{name}'>"); } - private void ClearMembers() + protected override void Clear() { - Runtime.Py_CLEAR(ref target); - Runtime.Py_CLEAR(ref targetType); - } - - protected override void Dealloc() - { - this.ClearMembers(); - base.Dealloc(); - } - - public static int tp_clear(IntPtr ob) - { - var self = (MethodBinding)GetManagedObject(ob); - self.ClearMembers(); - return 0; + Runtime.Py_CLEAR(ref this.target); + Runtime.Py_CLEAR(ref this.targetType); + base.Clear(); } protected override void OnSave(InterDomainContext context) diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index 5fa965f1b..2787ec999 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -200,29 +200,17 @@ public static IntPtr tp_repr(IntPtr ob) return Runtime.PyString_FromString($""); } - private void ClearMembers() + protected override void Clear() { - Runtime.Py_CLEAR(ref doc); - if (unbound != null) + Runtime.Py_CLEAR(ref this.doc); + if (this.unbound != null) { - Runtime.XDecref(unbound.pyHandle); - unbound = null; + Runtime.XDecref(this.unbound.pyHandle); + this.unbound = null; } - } - protected override void Dealloc() - { - this.ClearMembers(); ClearObjectDict(this.pyHandle); - base.Dealloc(); - } - - public static int tp_clear(IntPtr ob) - { - var self = (MethodObject)GetManagedObject(ob); - self.ClearMembers(); - ClearObjectDict(ob); - return 0; + base.Clear(); } protected override void OnSave(InterDomainContext context) diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index 1ab014c2a..606fa7be9 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -295,12 +295,6 @@ public static IntPtr tp_repr(IntPtr ob) return Runtime.PyString_FromString($""); } - protected override void Dealloc() - { - tp_clear(this.pyHandle); - base.Dealloc(); - } - public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg) { var self = (ModuleObject)GetManagedObject(ob); @@ -314,17 +308,16 @@ public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg) return 0; } - public static int tp_clear(IntPtr ob) + protected override void Clear() { - var self = (ModuleObject)GetManagedObject(ob); - Runtime.Py_CLEAR(ref self.dict); - ClearObjectDict(ob); - foreach (var attr in self.cache.Values) + Runtime.Py_CLEAR(ref this.dict); + ClearObjectDict(this.pyHandle); + foreach (var attr in this.cache.Values) { Runtime.XDecref(attr.pyHandle); } - self.cache.Clear(); - return 0; + this.cache.Clear(); + base.Clear(); } protected override void OnSave(InterDomainContext context) diff --git a/src/runtime/overload.cs b/src/runtime/overload.cs index 48fabca4a..8222dc136 100644 --- a/src/runtime/overload.cs +++ b/src/runtime/overload.cs @@ -58,10 +58,10 @@ public static IntPtr tp_repr(IntPtr op) return doc; } - protected override void Dealloc() + protected override void Clear() { Runtime.Py_CLEAR(ref this.target); - base.Dealloc(); + base.Clear(); } } }