fix performance issues with implicit parameter coercion

This commit is contained in:
David Rose 2009-01-07 20:05:57 +00:00
parent 82fccf788d
commit 4cd50fa68d
3 changed files with 93 additions and 52 deletions

View File

@ -2134,6 +2134,8 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
<< "PyObject *coerced = NULL;\n"; << "PyObject *coerced = NULL;\n";
indent(out,indent_level) indent(out,indent_level)
<< "PyObject **coerced_ptr = NULL;\n"; << "PyObject **coerced_ptr = NULL;\n";
indent(out,indent_level)
<< "bool report_errors = false;\n";
indent(out,indent_level) indent(out,indent_level)
<< "while (true) {\n"; << "while (true) {\n";
indent_level += 2; indent_level += 2;
@ -2219,16 +2221,28 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
if (coercion_possible) { if (coercion_possible) {
// Try again, this time with coercion enabled. // Try again, this time with coercion enabled.
indent(out,indent_level) indent(out,indent_level)
<< "if (coerced_ptr != NULL) {\n"; << "if (coerced_ptr == NULL && !report_errors) {\n";
indent(out,indent_level + 2) indent(out,indent_level + 2)
<< "break;\n"; << "coerced_ptr = &coerced;\n";
indent(out,indent_level + 2)
<< "continue;\n";
indent(out,indent_level) indent(out,indent_level)
<< "}\n"; << "}\n";
// No dice. Go back one more time, and this time get the error
// message.
indent(out,indent_level) indent(out,indent_level)
<< "PyErr_Clear();\n"; << "if (!report_errors) {\n";
indent(out,indent_level + 2)
<< "report_errors = true;\n";
indent(out,indent_level + 2)
<< "continue;\n";
indent(out,indent_level) indent(out,indent_level)
<< "coerced_ptr = &coerced;\n"; << "}\n";
// We've been through three times. We're done.
indent(out,indent_level)
<< "break;\n";
indent_level -= 2; indent_level -= 2;
indent(out,indent_level) indent(out,indent_level)
@ -2453,9 +2467,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
if (coercion_possible && !is_copy_constructor) { if (coercion_possible && !is_copy_constructor) {
// We never attempt to coerce a copy constructor parameter. // We never attempt to coerce a copy constructor parameter.
// That would lead to infinite recursion. // That would lead to infinite recursion.
str << ", coerced_ptr"; str << ", coerced_ptr, report_errors";
} else { } else {
str << ", NULL"; str << ", NULL, true";
} }
str << ");\n"; str << ");\n";

View File

@ -94,10 +94,24 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
// temporary object. Weird. // temporary object. Weird.
Py_DECREF(obj); Py_DECREF(obj);
} }
// Clear the error returned by the coercion constructor. It's not
// the error message we want to report.
PyErr_Clear();
} }
return NULL; return NULL;
} }
// Temporary function to preserve backward compatibility.
void *
DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
int param, const string &function_name, bool const_ok,
PyObject **coerced) {
return DTOOL_Call_GetPointerThisClass(self, classdef,
param, function_name, const_ok,
coerced, true);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: DTOOL_Call_GetPointerThisClass // Function: DTOOL_Call_GetPointerThisClass
// Description: Extracts the C++ pointer for an object, given its // Description: Extracts the C++ pointer for an object, given its
@ -140,7 +154,10 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
void * void *
DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
int param, const string &function_name, bool const_ok, int param, const string &function_name, bool const_ok,
PyObject **coerced) { PyObject **coerced, bool report_errors) {
if (PyErr_Occurred()) {
return NULL;
}
if (self != NULL) { if (self != NULL) {
if (DtoolCanThisBeAPandaInstance(self)) { if (DtoolCanThisBeAPandaInstance(self)) {
Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)self)->_My_Type; Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)self)->_My_Type;
@ -150,12 +167,15 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
return result; return result;
} }
if (report_errors) {
ostringstream str; ostringstream str;
str << function_name << "() argument " << param << " may not be const"; str << function_name << "() argument " << param << " may not be const";
string msg = str.str(); string msg = str.str();
PyErr_SetString(PyExc_TypeError, msg.c_str()); PyErr_SetString(PyExc_TypeError, msg.c_str());
}
} else { } else {
if (report_errors) {
ostringstream str; ostringstream str;
str << function_name << "() argument " << param << " must be "; str << function_name << "() argument " << param << " must be ";
@ -179,6 +199,7 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
string msg = str.str(); string msg = str.str();
PyErr_SetString(PyExc_TypeError, msg.c_str()); PyErr_SetString(PyExc_TypeError, msg.c_str());
} }
}
} else { } else {
// The parameter was not a Panda type. Can we coerce it to the // The parameter was not a Panda type. Can we coerce it to the
@ -189,6 +210,7 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
} }
// Coercion failed. // Coercion failed.
if (report_errors) {
ostringstream str; ostringstream str;
str << function_name << "() argument " << param << " must be "; str << function_name << "() argument " << param << " must be ";
@ -209,9 +231,12 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
string msg = str.str(); string msg = str.str();
PyErr_SetString(PyExc_TypeError, msg.c_str()); PyErr_SetString(PyExc_TypeError, msg.c_str());
} }
}
} else { } else {
if (report_errors) {
PyErr_SetString(PyExc_TypeError, "Self Is Null"); PyErr_SetString(PyExc_TypeError, "Self Is Null");
} }
}
return NULL; return NULL;
} }

View File

@ -364,6 +364,8 @@ EXPCL_DTOOLCONFIG bool DtoolCanThisBeAPandaInstance(PyObject *self);
EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer); EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer);
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced, bool report_errors);
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced); EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThis(PyObject *self); EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThis(PyObject *self);