mirror of
https://github.com/python/cpython
synced 2026-09-29 10:15:30 +03:00
Finish the previous checkin: also avoid getattr when calling the method
directly.
This commit is contained in:
parent
b5f17f2dc5
commit
2730b13202
1 changed files with 93 additions and 25 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue