diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-03-04 07:06:14 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-03-04 07:18:10 +0300 |
commit | 0d28e2a334a10d75c2c10054dddefabfc8766840 (patch) | |
tree | 11e9658a23f35ffd5e406c4bb0ed72f286747a57 /source | |
parent | 67856d8c4afa6a35b15f00ce24ebe54f403c9fc7 (diff) |
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.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 34 |
1 files 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 } } |