WIP: some bug and performance fixes.

This commit is contained in:
Matthias Koefferlein
2018-06-01 23:36:01 +02:00
parent 3882f6a3b1
commit 403840b109
4 changed files with 101 additions and 39 deletions
-10
View File
@@ -51,16 +51,6 @@ initialize ()
// merge the extensions to the main declaration // merge the extensions to the main declaration
gsi::ClassBase::merge_declarations (); gsi::ClassBase::merge_declarations ();
// do a full re-initialization - maybe merge_declarations modified existing classes too
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
// Initialize the method table once again after we have merged the declarations
// TODO: get rid of that const cast
(const_cast<gsi::ClassBase *> (&*c))->initialize ();
// there should be only main declarations since we merged
tl_assert (c->declaration () == &*c);
}
// build or rebuild the variant user class table // build or rebuild the variant user class table
// NOTE: as the variant classes are tied to the gsi::Class objects, we can rebuild the table // NOTE: as the variant classes are tied to the gsi::Class objects, we can rebuild the table
// and will get the same pointers for the classes that have been there before // and will get the same pointers for the classes that have been there before
+39 -5
View File
@@ -55,7 +55,7 @@ namespace {
static std::map<const std::type_info *, const ClassBase *, type_info_compare> s_ti_to_class; static std::map<const std::type_info *, const ClassBase *, type_info_compare> s_ti_to_class;
ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_register) ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_register)
: mp_base (0), mp_parent (0), m_doc (doc), m_methods (mm) : m_initialized (false), mp_base (0), mp_parent (0), m_doc (doc), m_methods (mm)
{ {
if (do_register) { if (do_register) {
@@ -79,13 +79,19 @@ ClassBase::~ClassBase ()
void void
ClassBase::set_parent (const ClassBase *p) ClassBase::set_parent (const ClassBase *p)
{ {
mp_parent = p; if (mp_parent != p) {
mp_parent = p;
m_initialized = false;
}
} }
void void
ClassBase::set_base (const ClassBase *b) ClassBase::set_base (const ClassBase *b)
{ {
mp_base = b; if (mp_base != b) {
mp_base = b;
m_initialized = false;
}
} }
std::string std::string
@@ -100,6 +106,15 @@ ClassBase::qname () const
return qn; return qn;
} }
void
ClassBase::add_subclass (const ClassBase *cls)
{
// TODO: ugly const_cast hack
ClassBase *non_const_cls = const_cast<ClassBase *> (cls);
m_subclasses.push_back (non_const_cls);
m_initialized = false;
}
void void
ClassBase::add_child_class (const ClassBase *cls) ClassBase::add_child_class (const ClassBase *cls)
{ {
@@ -109,6 +124,7 @@ ClassBase::add_child_class (const ClassBase *cls)
// child classes inherit the module of their parent // child classes inherit the module of their parent
non_const_cls->set_module (module ()); non_const_cls->set_module (module ());
m_child_classes.push_back (non_const_cls); m_child_classes.push_back (non_const_cls);
m_initialized = false;
} }
bool bool
@@ -395,7 +411,7 @@ ClassBase::merge_declarations ()
// Consolidate the classes (merge, remove etc.) // Consolidate the classes (merge, remove etc.)
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) {
if (! c->consolidate()) { if (! c->consolidate ()) {
to_remove.push_back (&*c); to_remove.push_back (&*c);
} }
} }
@@ -410,7 +426,7 @@ ClassBase::merge_declarations ()
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) {
if (c->base ()) { if (c->base ()) {
// TODO: ugly const_cast hack // TODO: ugly const_cast hack
const_cast<gsi::ClassBase *> (c->base ())->m_subclasses.push_back (const_cast<gsi::ClassBase *> (c.operator-> ())); const_cast<gsi::ClassBase *> (c->base ())->add_subclass (c.operator-> ());
} }
} }
@@ -499,11 +515,26 @@ ClassBase::merge_declarations ()
mp_class_collection->push_back (non_const_decl); mp_class_collection->push_back (non_const_decl);
} }
mp_new_class_collection->clear (); mp_new_class_collection->clear ();
// do a full re-initialization - maybe merge_declarations modified existing classes too
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
// Initialize the method table once again after we have merged the declarations
// TODO: get rid of that const cast
(const_cast<gsi::ClassBase *> (&*c))->initialize ();
// there should be only main declarations since we merged
tl_assert (c->declaration () == &*c);
}
} }
void void
ClassBase::initialize () ClassBase::initialize ()
{ {
// don't initialize again
if (m_initialized) {
return;
}
m_methods.initialize (); m_methods.initialize ();
m_constructors.clear (); m_constructors.clear ();
@@ -519,11 +550,14 @@ ClassBase::initialize ()
m_callbacks.push_back (*m); m_callbacks.push_back (*m);
} }
} }
m_initialized = true;
} }
void void
ClassBase::add_method (MethodBase *method, bool /*base_class*/) ClassBase::add_method (MethodBase *method, bool /*base_class*/)
{ {
m_initialized = false;
m_methods.add_method (method); m_methods.add_method (method);
} }
+7
View File
@@ -188,6 +188,12 @@ public:
*/ */
void add_child_class (const ClassBase *cls); void add_child_class (const ClassBase *cls);
/**
* @brief Adds a subclass
* Subclasses are the ones that derive from us (opposite of base)
*/
void add_subclass (const ClassBase *cls);
/** /**
* @brief Iterates all child classes (begin) * @brief Iterates all child classes (begin)
*/ */
@@ -595,6 +601,7 @@ protected:
void set_base (const ClassBase *base); void set_base (const ClassBase *base);
private: private:
bool m_initialized;
const ClassBase *mp_base, *mp_parent; const ClassBase *mp_base, *mp_parent;
std::string m_doc; std::string m_doc;
Methods m_methods; Methods m_methods;
+55 -24
View File
@@ -2223,21 +2223,7 @@ PythonModule::PythonModule ()
PythonModule::~PythonModule () PythonModule::~PythonModule ()
{ {
PYAObjectBase::clear_callbacks_cache (); PYAObjectBase::clear_callbacks_cache ();
delete_module ();
while (!m_methods_heap.empty ()) {
delete m_methods_heap.back ();
m_methods_heap.pop_back ();
}
while (!m_getseters_heap.empty ()) {
delete m_getseters_heap.back ();
m_getseters_heap.pop_back ();
}
if (mp_mod_def) {
delete[] mp_mod_def;
mp_mod_def = 0;
}
} }
PyObject * PyObject *
@@ -2256,6 +2242,22 @@ void
PythonModule::delete_module () PythonModule::delete_module ()
{ {
mp_module = PythonRef (); mp_module = PythonRef ();
mp_base_class = PythonRef ();
while (!m_methods_heap.empty ()) {
delete m_methods_heap.back ();
m_methods_heap.pop_back ();
}
while (!m_getseters_heap.empty ()) {
delete m_getseters_heap.back ();
m_getseters_heap.pop_back ();
}
if (mp_mod_def) {
delete[] mp_mod_def;
mp_mod_def = 0;
}
} }
void void
@@ -2283,12 +2285,13 @@ PythonModule::init (const char *mod_name, const char *description)
module_methods module_methods
}; };
tl_assert (mp_mod_def == 0); tl_assert (! mp_mod_def);
// prepare a persistent structure with the module definition // prepare a persistent structure with the module definition
// and pass this one to PyModule_Create // and pass this one to PyModule_Create
mp_mod_def = new char[sizeof (PyModuleDef)]; mp_mod_def = new char[sizeof (PyModuleDef)];
memcpy ((void *) mp_mod_def, (const void *) &mod_def, sizeof (PyModuleDef)); memcpy ((void *) mp_mod_def, (const void *) &mod_def, sizeof (PyModuleDef));
module = PyModule_Create ((PyModuleDef *) mp_mod_def); module = PyModule_Create ((PyModuleDef *) mp_mod_def);
#endif #endif
@@ -2350,6 +2353,39 @@ PythonModule::python_doc (const gsi::MethodBase *method)
void void
PythonModule::make_classes (const char *mod_name) PythonModule::make_classes (const char *mod_name)
{ {
// Check whether the new classes are self-contained within this module
if (mod_name) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->module () != mod_name) {
// don't handle classes outside this module
continue;
}
if (m_rev_cls_map.find (&*c) != m_rev_cls_map.end ()) {
// don't handle classes twice
continue;
}
// All child classes must originate from this module or be known already
for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = c->begin_child_classes (); cc != c->end_child_classes (); ++cc) {
if (m_rev_cls_map.find (cc->declaration ()) == m_rev_cls_map.end ()
&& cc->module () != mod_name) {
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, cc->module (), cc->name (), cc->module (), mod_name));
}
}
// Same for base class
if (c->base () && m_rev_cls_map.find (c->base ()) == m_rev_cls_map.end ()
&& c->base ()->module () != mod_name) {
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, c->base ()->module (), c->base ()->name (), c->base ()->module (), mod_name));
}
}
}
PyObject *module = mp_module.get (); PyObject *module = mp_module.get ();
// Prepare an __all__ index for the module // Prepare an __all__ index for the module
@@ -2426,9 +2462,6 @@ PythonModule::make_classes (const char *mod_name)
for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = c->begin_child_classes (); cc != c->end_child_classes (); ++cc) { for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = c->begin_child_classes (); cc != c->end_child_classes (); ++cc) {
tl_assert (cc->declaration () != 0); tl_assert (cc->declaration () != 0);
if (m_rev_cls_map.find (cc->declaration ()) == m_rev_cls_map.end ()) { if (m_rev_cls_map.find (cc->declaration ()) == m_rev_cls_map.end ()) {
if (mod_name && cc->module () != mod_name) {
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, cc->module (), cc->name (), cc->module (), mod_name));
}
all_children_available = false; all_children_available = false;
break; break;
} }
@@ -2440,9 +2473,6 @@ PythonModule::make_classes (const char *mod_name)
} }
if (c->base () && m_rev_cls_map.find (c->base ()) == m_rev_cls_map.end ()) { if (c->base () && m_rev_cls_map.find (c->base ()) == m_rev_cls_map.end ()) {
if (mod_name && c->base ()->module () != mod_name) {
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, c->base ()->module (), c->base ()->name (), c->base ()->module (), mod_name));
}
// can't produce this class yet. The base class needs to be handled first. // can't produce this class yet. The base class needs to be handled first.
more_classes = true; more_classes = true;
continue; continue;
@@ -2478,8 +2508,9 @@ PythonModule::make_classes (const char *mod_name)
PyList_Append (all_list.get (), PythonRef (c2python (c->name ())).get ()); PyList_Append (all_list.get (), PythonRef (c2python (c->name ())).get ());
PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type); PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type);
m_cls_map.insert (std::make_pair (type, &*c)); // NOTE: we force the new values as there may be value from a previous (failed) attempt
m_rev_cls_map.insert (std::make_pair (&*c, type)); m_cls_map[type] = c.operator-> ();
m_rev_cls_map[c.operator-> ()] = type;
// Create the sub-class attributes // Create the sub-class attributes