Finish the previous checkin: also avoid getattr when calling the method
authorGuido van Rossum <guido@python.org>
Tue, 28 Aug 2001 18:22:14 +0000 (18:22 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 28 Aug 2001 18:22:14 +0000 (18:22 +0000)
directly.

Objects/typeobject.c

index 7fb6c8a2485f27765e5de1c14d5c63e67ceafa61..476926c254e67d354704b015fa53a506511c18d3 100644 (file)
@@ -319,6 +319,55 @@ lookup_method(PyObject *self, char *attrstr, PyObject **attrobj)
        return res;
 }
 
+/* A variation of PyObject_CallMethod that uses lookup_method()
+   instead of PyObject_GetAttrString().  This uses the same convention
+   as lookup_method to cache the interned name string object. */
+
+PyObject *
+call_method(PyObject *o, char *name, PyObject **nameobj, char *format, ...)
+{
+       va_list va;
+       PyObject *args, *func = 0, *retval;
+       PyObject *dummy_str = NULL;
+       va_start(va, format);
+
+       func = lookup_method(o, name, &dummy_str);
+       Py_XDECREF(dummy_str);
+       if (func == NULL) {
+               va_end(va);
+               PyErr_SetString(PyExc_AttributeError, name);
+               return 0;
+       }
+
+       if (format && *format)
+               args = Py_VaBuildValue(format, va);
+       else
+               args = PyTuple_New(0);
+
+       va_end(va);
+
+       if (!args)
+               return NULL;
+
+       if (!PyTuple_Check(args)) {
+               PyObject *a;
+
+               a = PyTuple_New(1);
+               if (a == NULL)
+                       return NULL;
+               if (PyTuple_SetItem(a, 0, args) < 0)
+                       return NULL;
+               args = a;
+       }
+
+       retval = PyObject_CallObject(func, args);
+
+       Py_DECREF(args);
+       Py_DECREF(func);
+
+       return retval;
+}
+
 /* Method resolution order algorithm from "Putting Metaclasses to Work"
    by Forman and Danforth (Addison-Wesley 1999). */
 
@@ -2341,14 +2390,16 @@ add_operators(PyTypeObject *type)
 static PyObject * \
 FUNCNAME(PyObject *self) \
 { \
-       return PyObject_CallMethod(self, OPSTR, ""); \
+       static PyObject cache_str; \
+       return call_method(self, OPSTR, &cache_str, ""); \
 }
 
 #define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
 static PyObject * \
 FUNCNAME(PyObject *self, ARG1TYPE arg1) \
 { \
-       return PyObject_CallMethod(self, OPSTR, ARGCODES, arg1); \
+       static PyObject *cache_str; \
+       return call_method(self, OPSTR, &cache_str, ARGCODES, arg1); \
 }
 
 
@@ -2356,11 +2407,12 @@ FUNCNAME(PyObject *self, ARG1TYPE arg1) \
 static PyObject * \
 FUNCNAME(PyObject *self, PyObject *other) \
 { \
+       static PyObject *cache_str, *rcache_str; \
        if (self->ob_type->tp_as_number != NULL && \
            self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
                PyObject *r; \
-               r = PyObject_CallMethod( \
-                       self, OPSTR, "O", other); \
+               r = call_method( \
+                       self, OPSTR, &cache_str, "O", other); \
                if (r != Py_NotImplemented || \
                    other->ob_type == self->ob_type) \
                        return r; \
@@ -2368,8 +2420,8 @@ FUNCNAME(PyObject *self, PyObject *other) \
        } \
        if (other->ob_type->tp_as_number != NULL && \
            other->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
-               return PyObject_CallMethod( \
-                       other, ROPSTR, "O", self); \
+               return call_method( \
+                       other, ROPSTR, &rcache_str, "O", self); \
        } \
        Py_INCREF(Py_NotImplemented); \
        return Py_NotImplemented; \
@@ -2382,13 +2434,15 @@ FUNCNAME(PyObject *self, PyObject *other) \
 static PyObject * \
 FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \
 { \
-       return PyObject_CallMethod(self, OPSTR, ARGCODES, arg1, arg2); \
+       static PyObject *cache_str; \
+       return call_method(self, OPSTR, &cache_str, ARGCODES, arg1, arg2); \
 }
 
 static int
 slot_sq_length(PyObject *self)
 {
-       PyObject *res = PyObject_CallMethod(self, "__len__", "");
+       static PyObject *len_str;
+       PyObject *res = call_method(self, "__len__", &len_str, "");
 
        if (res == NULL)
                return -1;
@@ -2404,12 +2458,14 @@ static int
 slot_sq_ass_item(PyObject *self, int index, PyObject *value)
 {
        PyObject *res;
+       static PyObject *delitem_str, *setitem_str;
 
        if (value == NULL)
-               res = PyObject_CallMethod(self, "__delitem__", "i", index);
+               res = call_method(self, "__delitem__", &delitem_str,
+                                 "i", index);
        else
-               res = PyObject_CallMethod(self, "__setitem__",
-                                         "iO", index, value);
+               res = call_method(self, "__setitem__", &setitem_str,
+                                 "iO", index, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);
@@ -2420,12 +2476,14 @@ static int
 slot_sq_ass_slice(PyObject *self, int i, int j, PyObject *value)
 {
        PyObject *res;
+       static PyObject *delslice_str, *setslice_str;
 
        if (value == NULL)
-               res = PyObject_CallMethod(self, "__delslice__", "ii", i, j);
+               res = call_method(self, "__delslice__", &delslice_str,
+                                 "ii", i, j);
        else
-               res = PyObject_CallMethod(self, "__setslice__",
-                                         "iiO", i, j, value);
+               res = call_method(self, "__setslice__", &setslice_str,
+                                 "iiO", i, j, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);
@@ -2470,12 +2528,14 @@ static int
 slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
 {
        PyObject *res;
+       static PyObject *delitem_str, *setitem_str;
 
        if (value == NULL)
-               res = PyObject_CallMethod(self, "__delitem__", "O", key);
+               res = call_method(self, "__delitem__", &delitem_str,
+                                 "O", key);
        else
-               res = PyObject_CallMethod(self, "__setitem__",
-                                         "OO", key, value);
+               res = call_method(self, "__setitem__", &setitem_str,
+                                "OO", key, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);
@@ -2497,10 +2557,13 @@ SLOT1BINFULL(slot_nb_power_binary, slot_nb_power,
 static PyObject *
 slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus)
 {
+       static PyObject *pow_str;
+
        if (modulus == Py_None)
                return slot_nb_power_binary(self, other);
        /* Three-arg power doesn't use __rpow__ */
-       return PyObject_CallMethod(self, "__pow__", "OO", other, modulus);
+       return call_method(self, "__pow__", &pow_str,
+                          "OO", other, modulus);
 }
 
 SLOT0(slot_nb_negative, "__neg__")
@@ -2727,12 +2790,14 @@ static int
 slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value)
 {
        PyObject *res;
+       static PyObject *delattr_str, *setattr_str;
 
        if (value == NULL)
-               res = PyObject_CallMethod(self, "__delattr__", "O", name);
+               res = call_method(self, "__delattr__", &delattr_str,
+                                 "O", name);
        else
-               res = PyObject_CallMethod(self, "__setattr__",
-                                         "OO", name, value);
+               res = call_method(self, "__setattr__", &setattr_str,
+                                 "OO", name, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);
@@ -2822,7 +2887,8 @@ slot_tp_iter(PyObject *self)
 static PyObject *
 slot_tp_iternext(PyObject *self)
 {
-       return PyObject_CallMethod(self, "next", "");
+       static PyObject *next_str;
+       return call_method(self, "next", &next_str, "");
 }
 
 static PyObject *
@@ -2856,12 +2922,14 @@ static int
 slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value)
 {
        PyObject *res;
+       static PyObject *del_str, *set_str;
 
        if (value == NULL)
-               res = PyObject_CallMethod(self, "__del__", "O", target);
+               res = call_method(self, "__del__", &del_str,
+                                 "O", target);
        else
-               res = PyObject_CallMethod(self, "__set__",
-                                         "OO", target, value);
+               res = call_method(self, "__set__", &set_str,
+                                 "OO", target, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);