From fdcfaf69b0b2719a79aee5ca12c093087580db81 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 15 Dec 2022 20:25:48 +0100 Subject: [PATCH] interrogate: Optimizate creating Python wrapper instances Fewer function pointer calls by moving the wrapper creation logic to the downcast function This also paves the way for some classes to have custom wrapper creation logic --- .../interfaceMakerPythonNative.cxx | 25 +++++++++++----- dtool/src/interrogatedb/dtool_super_base.cxx | 6 ++-- dtool/src/interrogatedb/py_panda.cxx | 30 ++++++++----------- dtool/src/interrogatedb/py_panda.h | 5 ++-- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 337869acc9..04ea293c1a 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -1221,22 +1221,33 @@ write_class_details(ostream &out, Object *obj) { out << " return nullptr;\n"; out << "}\n\n"; - out << "static void *Dtool_DowncastInterface_" << ClassName << "(void *from_this, Dtool_PyTypedObject *from_type) {\n"; + out << "static Dtool_PyInstDef *Dtool_Wrap_" << ClassName << "(void *from_this, Dtool_PyTypedObject *from_type) {\n"; out << " if (from_this == nullptr || from_type == nullptr) {\n"; out << " return nullptr;\n"; out << " }\n"; - out << " if (from_type == Dtool_Ptr_" << ClassName << ") {\n"; - out << " return from_this;\n"; + out << " " << cClassName << " *to_this;\n"; + out << " if (from_type == &Dtool_" << ClassName << ") {\n"; + out << " to_this = (" << cClassName << "*)from_this;\n"; out << " }\n"; for (di = details.begin(); di != details.end(); di++) { if (di->second._can_downcast && di->second._is_legal_py_class) { - out << " if (from_type == Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; + out << " else if (from_type == Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; out << " " << di->second._to_class_name << "* other_this = (" << di->second._to_class_name << "*)from_this;\n" ; - out << " return (" << cClassName << "*)other_this;\n"; + out << " to_this = (" << cClassName << "*)other_this;\n"; out << " }\n"; } } - out << " return nullptr;\n"; + out << " else {\n"; + out << " return nullptr;\n"; + out << " }\n"; + out << " // Allocate a new Python instance\n"; + out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; + out << " self->_signature = PY_PANDA_SIGNATURE;\n"; + out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; + out << " self->_ptr_to_object = to_this;\n"; + out << " self->_memory_rules = false;\n"; + out << " self->_is_const = false;\n"; + out << " return self;\n"; out << "}\n\n"; } } @@ -3251,7 +3262,7 @@ write_module_class(ostream &out, Object *obj) { out << " TypeHandle::none(),\n"; out << " Dtool_PyModuleClassInit_" << ClassName << ",\n"; out << " Dtool_UpcastInterface_" << ClassName << ",\n"; - out << " Dtool_DowncastInterface_" << ClassName << ",\n"; + out << " Dtool_Wrap_" << ClassName << ",\n"; int has_coerce = has_coerce_constructor(obj->_itype._cpptype->as_struct_type()); if (has_coerce > 0) { diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx index 918ab36cc8..1af473e142 100644 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ b/dtool/src/interrogatedb/dtool_super_base.cxx @@ -39,11 +39,11 @@ static void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) { } } -static void *Dtool_DowncastInterface_DTOOL_SUPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) { +static void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) { return nullptr; } -static void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) { +static Dtool_PyInstDef *Dtool_Wrap_DTOOL_SUPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) { return nullptr; } @@ -140,7 +140,7 @@ Dtool_PyTypedObject *Dtool_GetSuperBase() { TypeHandle::none(), Dtool_PyModuleClassInit_DTOOL_SUPER_BASE, Dtool_UpcastInterface_DTOOL_SUPER_BASE, - Dtool_DowncastInterface_DTOOL_SUPER_BASE, + Dtool_Wrap_DTOOL_SUPER_BASE, nullptr, nullptr, }; diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index ae6483f5b1..d4fdd789f9 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -458,31 +458,24 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)TypeHandle::from_index(type_index).get_python_type(); if (target_class != nullptr) { // cast to the type... - void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type); - if (new_local_this != nullptr) { - // ask class to allocate an instance.. - Dtool_PyInstDef *self = (Dtool_PyInstDef *) target_class->_PyType.tp_new(&target_class->_PyType, nullptr, nullptr); - if (self != nullptr) { - self->_ptr_to_object = new_local_this; - self->_memory_rules = memory_rules; - self->_is_const = is_const; - // self->_signature = PY_PANDA_SIGNATURE; - self->_My_Type = target_class; - return (PyObject *)self; - } + Dtool_PyInstDef *self = target_class->_Dtool_WrapInterface(local_this_in, &known_class_type); + if (self != nullptr) { + self->_memory_rules = memory_rules; + self->_is_const = is_const; + return (PyObject *)self; } } } // if we get this far .. just wrap the thing in the known type ?? better // than aborting...I guess.... - Dtool_PyInstDef *self = (Dtool_PyInstDef *) known_class_type._PyType.tp_new(&known_class_type._PyType, nullptr, nullptr); + Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&known_class_type._PyType, 0); if (self != nullptr) { + self->_signature = PY_PANDA_SIGNATURE; + self->_My_Type = &known_class_type; self->_ptr_to_object = local_this_in; self->_memory_rules = memory_rules; self->_is_const = is_const; - // self->_signature = PY_PANDA_SIGNATURE; - self->_My_Type = &known_class_type; } return (PyObject *)self; } @@ -497,13 +490,14 @@ PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_class return Py_None; } - Dtool_PyTypedObject *classdef = &in_classdef; - Dtool_PyInstDef *self = (Dtool_PyInstDef *) classdef->_PyType.tp_new(&classdef->_PyType, nullptr, nullptr); + Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&in_classdef._PyType, 0); if (self != nullptr) { + self->_signature = PY_PANDA_SIGNATURE; + self->_My_Type = &in_classdef; self->_ptr_to_object = local_this; self->_memory_rules = memory_rules; self->_is_const = is_const; - self->_My_Type = classdef; + self->_My_Type = &in_classdef; } return (PyObject *)self; } diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 026d1c6858..8a42f9a37f 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -35,12 +35,13 @@ using namespace std; #define IMPORT_THIS extern #endif +struct Dtool_PyInstDef; struct Dtool_PyTypedObject; // used to stamp dtool instance.. #define PY_PANDA_SIGNATURE 0xbeaf typedef void *(*UpcastFunction)(PyObject *,Dtool_PyTypedObject *); -typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *); +typedef Dtool_PyInstDef *(*WrapFunction)(void *, Dtool_PyTypedObject *); typedef void *(*CoerceFunction)(PyObject *, void *); typedef void (*ModuleClassInitFunction)(PyObject *module); @@ -78,7 +79,7 @@ struct Dtool_PyTypedObject { ModuleClassInitFunction _Dtool_ModuleClassInit; UpcastFunction _Dtool_UpcastInterface; // The Upcast Function By Slot - DowncastFunction _Dtool_DowncastInterface; // The Downcast Function By Slot + WrapFunction _Dtool_WrapInterface; // The Downcast Function By Slot CoerceFunction _Dtool_ConstCoerce; CoerceFunction _Dtool_Coerce;