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
This commit is contained in:
rdb 2022-12-15 20:25:48 +01:00
parent cce46b5edb
commit fdcfaf69b0
4 changed files with 36 additions and 30 deletions

View File

@ -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) {

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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;