diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-04-26 20:39:20 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-04-26 20:39:20 (GMT) |
commit | 9e392e2412308c7923195f226510bb1f174be215 (patch) | |
tree | 234c290c12a4cba247e7fd044e0cbb0998180636 | |
parent | 50422b403c4ebea87f7af840e5c5cf147155639e (diff) | |
download | cpython-9e392e2412308c7923195f226510bb1f174be215.zip cpython-9e392e2412308c7923195f226510bb1f174be215.tar.gz cpython-9e392e2412308c7923195f226510bb1f174be215.tar.bz2 |
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.
-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 4fb1167..6c7dba5 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) { |