diff options
| author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-04-26 20:39:20 +0000 | 
|---|---|---|
| committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-04-26 20:39:20 +0000 | 
| commit | 9e392e2412308c7923195f226510bb1f174be215 (patch) | |
| tree | 234c290c12a4cba247e7fd044e0cbb0998180636 /Objects/classobject.c | |
| parent | 50422b403c4ebea87f7af840e5c5cf147155639e (diff) | |
| download | cpython-git-9e392e2412308c7923195f226510bb1f174be215.tar.gz | |
potentially useless optimization
The previous checkin (2.84) added a PyErr_Format call that made the
cost of raising an AttributeError much more expensive.  In general
this doesn't matter, except that checks for __init__ and
__del__ methods, where exceptions are caught and cleared in C, also
got much more expensive.
The fix is to split instance_getattr1 into two calls:
instance_getattr2 checks the instance and the class for the attribute
and returns it or returns NULL on error.  It does not raise an
exception.
instance_getattr1 does rexec checks, then calls instance_getattr2.  It
raises an exception if instance_getattr2 returns NULL.
PyInstance_New and instance_dealloc now call instance_getattr2
directly.
Diffstat (limited to 'Objects/classobject.c')
| -rw-r--r-- | Objects/classobject.c | 31 | 
1 files changed, 20 insertions, 11 deletions
| diff --git a/Objects/classobject.c b/Objects/classobject.c index 4fb1167489..6c7dba5f4e 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -38,6 +38,7 @@ PERFORMANCE OF THIS SOFTWARE.  static PyObject *class_lookup  	Py_PROTO((PyClassObject *, PyObject *, PyClassObject **));  static PyObject *instance_getattr1 Py_PROTO((PyInstanceObject *, PyObject *)); +static PyObject *instance_getattr2 Py_PROTO((PyInstanceObject *, PyObject *));  static PyObject *getattrstr, *setattrstr, *delattrstr; @@ -456,9 +457,8 @@ PyInstance_New(class, arg, kw)  	}  	if (initstr == NULL)  		initstr = PyString_InternFromString("__init__"); -	init = instance_getattr1(inst, initstr); +	init = instance_getattr2(inst, initstr);  	if (init == NULL) { -		PyErr_Clear();  		if ((arg != NULL && (!PyTuple_Check(arg) ||  				     PyTuple_Size(arg) != 0))  		    || (kw != NULL && (!PyDict_Check(kw) || @@ -515,7 +515,7 @@ instance_dealloc(inst)  	PyErr_Fetch(&error_type, &error_value, &error_traceback);  	if (delstr == NULL)  		delstr = PyString_InternFromString("__del__"); -	if ((del = instance_getattr1(inst, delstr)) != NULL) { +	if ((del = instance_getattr2(inst, delstr)) != NULL) {  		PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);  		if (res == NULL) {  			PyObject *f, *t, *v, *tb; @@ -571,7 +571,6 @@ instance_getattr1(inst, name)  {  	register PyObject *v;  	register char *sname = PyString_AsString(name); -	PyClassObject *class;  	if (sname[0] == '_' && sname[1] == '_') {  		if (strcmp(sname, "__dict__") == 0) {  			if (PyEval_GetRestricted()) { @@ -587,17 +586,27 @@ instance_getattr1(inst, name)  			return (PyObject *)inst->in_class;  		}  	} +	v = instance_getattr2(inst, name); +	if (v == NULL) { +		PyErr_Format(PyExc_AttributeError,"'%.50s' instance has no attribute '%.400s'", +			     PyString_AS_STRING(inst->in_class->cl_name), sname); +	} +	return v; +} + +static PyObject * +instance_getattr2(inst, name) +	register PyInstanceObject *inst; +	PyObject *name; +{ +	register PyObject *v; +	PyClassObject *class;  	class = NULL;  	v = PyDict_GetItem(inst->in_dict, name);  	if (v == NULL) {  		v = class_lookup(inst->in_class, name, &class); -		if (v == NULL) { -			PyErr_Format(PyExc_AttributeError, -				     "'%.50s' instance has no attribute '%.400s'", -				     PyString_AsString(inst->in_class->cl_name), -				     sname); -			return NULL; -		} +		if (v == NULL) +			return v;  	}  	Py_INCREF(v);  	if (class != NULL) { | 
