]> granicus.if.org Git - python/commitdiff
potentially useless optimization
authorJeremy Hylton <jeremy@alum.mit.edu>
Wed, 26 Apr 2000 20:39:20 +0000 (20:39 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Wed, 26 Apr 2000 20:39:20 +0000 (20:39 +0000)
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.

Objects/classobject.c

index 4fb1167489ed134ead2a22373942a820fa453d22..6c7dba5f4edd01564e614f9e6a4cfa0f435420b3 100644 (file)
@@ -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) {