From 0d28e2a334a10d75c2c10054dddefabfc8766840 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Mar 2021 15:06:14 +1100 Subject: PyAPI: correct garbage collection for StructRNA types By default objects are no longer GC tracked, this removes some overhead although it's not significant in my own testing. - Only enable GC for StructRNA when 'WITH_PYTHON_SAFETY' is on. - Only track StructRNA when their 'reference' is set. - Add missing NULL check when 'WITH_PYTHON_SAFETY' is on and objects new objects be created. --- source/blender/python/intern/bpy_rna.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 555dd41b228..a006b81cb60 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1204,15 +1204,15 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self) static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) { if (self->reference) { - // PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ - pyrna_struct_clear(self); + PyObject_GC_UnTrack(self); + Py_CLEAR(self->reference); } /* Reference is now NULL. */ if (reference) { self->reference = reference; Py_INCREF(reference); - // PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ + PyObject_GC_Track(self); } } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -5822,6 +5822,11 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * BPy_StructRNA *ret; if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { ret->ptr = base->ptr; +#ifdef USE_PYRNA_STRUCT_REFERENCE + /* #PyType_GenericAlloc will have set tracking. + * We only want tracking when `StructRNA.reference` has been set. */ + PyObject_GC_UnTrack(ret); +#endif } /* Pass on exception & NULL if tp_alloc fails. */ return (PyObject *)ret; @@ -6525,7 +6530,11 @@ PyTypeObject pyrna_struct_Type = { NULL, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE +#ifdef USE_PYRNA_STRUCT_REFERENCE + | Py_TPFLAGS_HAVE_GC +#endif + , /* long tp_flags; */ NULL, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ @@ -7462,13 +7471,28 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) if (tp) { pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0); +#ifdef USE_PYRNA_STRUCT_REFERENCE + /* #PyType_GenericAlloc will have set tracking. + * We only want tracking when `StructRNA.reference` has been set. */ + if (pyrna != NULL) { + PyObject_GC_UnTrack(pyrna); + } +#endif Py_DECREF(tp); /* srna owns, can't hold a reference. */ } else { CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); + +#ifdef USE_PYRNA_STRUCT_REFERENCE pyrna = (BPy_StructRNA *)PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); +#else + pyrna = (BPy_StructRNA *)PyObject_New(BPy_StructRNA, &pyrna_struct_Type); +#endif + #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + if (pyrna != NULL) { + pyrna->in_weakreflist = NULL; + } #endif } } -- cgit v1.2.3