Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-12-11 10:37:54 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-12-11 10:37:54 +0300
commitdd4e0cd3e30a88657981064c3f8fcd81612d9394 (patch)
tree341da6965d0831bca04de682ca64369c1e707590 /source/blender/python
parentc5689851186392407eab3ce3801db3270ce84cb6 (diff)
DNA/RNA: add 'py_instance' for ID types
Avoid creating new Python instances every time a scene, object, mesh .. etc are accessed. Also resolves crashes T28724, T53530 although it's only valid for ID types, not modifiers vertices etc. Back-ported from blender2.8 branch.
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/intern/bpy_rna.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 1a9fd920af5..deb045c514b 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -6762,7 +6762,30 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */
Py_RETURN_NONE;
}
- else {
+
+ /* New in 2.8x, since not many types support instancing
+ * we may want to use a flag to avoid looping over all classes. - campbell */
+ void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL;
+ if (instance && *instance) {
+ pyrna = *instance;
+
+ /* Refine may have changed types after the first instance was created. */
+ if (ptr->type == pyrna->ptr.type) {
+ Py_INCREF(pyrna);
+ return (PyObject *)pyrna;
+ }
+ else {
+ /* Existing users will need to use 'type_recast' method. */
+ Py_DECREF(pyrna);
+ *instance = NULL;
+ /* Continue as if no instance was made */
+#if 0 /* no need to assign, will be written to next... */
+ pyrna = NULL;
+#endif
+ }
+ }
+
+ {
PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr);
if (tp) {
@@ -6783,6 +6806,12 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
return NULL;
}
+ /* Blender's instance owns a reference (to avoid Python freeing it). */
+ if (instance) {
+ *instance = pyrna;
+ Py_INCREF(pyrna);
+ }
+
pyrna->ptr = *ptr;
#ifdef PYRNA_FREE_SUPPORT
pyrna->freeptr = false;
@@ -7547,7 +7576,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyObject *args;
PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem;
PyTypeObject *py_class;
- void **py_class_instance_store = NULL;
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
@@ -7562,7 +7590,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
- const bool is_operator = RNA_struct_is_a(ptr->type, &RNA_Operator);
+ const bool is_readonly_init = !RNA_struct_is_a(ptr->type, &RNA_Operator);
// const char *func_id = RNA_function_identifier(func); /* UNUSED */
/* testing, for correctness, not operator and not draw function */
const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
@@ -7597,10 +7625,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
py_class_instance = *instance;
Py_INCREF(py_class_instance);
}
- else {
- /* store the instance here once its created */
- py_class_instance_store = instance;
- }
}
}
/* end exception */
@@ -7627,7 +7651,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (py_class->tp_init) {
#ifdef USE_PEDANTIC_WRITE
const int prev_write = rna_disallow_writes;
- rna_disallow_writes = is_operator ? false : true; /* only operators can write on __init__ */
+ rna_disallow_writes = is_readonly_init ? false : true; /* only operators can write on __init__ */
#endif
/* true in most cases even when the class its self doesn't define an __init__ function. */
@@ -7671,10 +7695,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (py_class_instance == NULL) {
err = -1; /* so the error is not overridden below */
}
- else if (py_class_instance_store) {
- *py_class_instance_store = py_class_instance;
- Py_INCREF(py_class_instance);
- }
}
}