mirror of https://github.com/python/cpython
bpo-30509: Clean up calling type slots. (#1883)
Also speed up slot_sq_item.
This commit is contained in:
parent
56ddfd2eea
commit
4e624ca50a
|
@ -1398,29 +1398,23 @@ PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
|
||||||
return type_is_subtype_base_chain(a, b);
|
return type_is_subtype_base_chain(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal routines to do a method lookup in the type
|
/* Routines to do a method lookup in the type without looking in the
|
||||||
without looking in the instance dictionary
|
instance dictionary (so we can't use PyObject_GetAttr) but still
|
||||||
(so we can't use PyObject_GetAttr) but still binding
|
binding it to the instance.
|
||||||
it to the instance. The arguments are the object,
|
|
||||||
the method name as a C string, and the address of a
|
|
||||||
static variable used to cache the interned Python string.
|
|
||||||
|
|
||||||
Variants:
|
Variants:
|
||||||
|
|
||||||
- lookup_maybe() returns NULL without raising an exception
|
- _PyObject_LookupSpecial() returns NULL without raising an exception
|
||||||
when the _PyType_Lookup() call fails;
|
when the _PyType_Lookup() call fails;
|
||||||
|
|
||||||
- lookup_maybe_method() and lookup_method() are similar to
|
- lookup_maybe_method() and lookup_method() are internal routines similar
|
||||||
lookup_maybe(), but can return unbound PyFunction
|
to _PyObject_LookupSpecial(), but can return unbound PyFunction
|
||||||
to avoid temporary method object. Pass self as first argument when
|
to avoid temporary method object. Pass self as first argument when
|
||||||
unbound == 1.
|
unbound == 1.
|
||||||
|
|
||||||
- _PyObject_LookupSpecial() expose lookup_maybe for the benefit of
|
|
||||||
other places.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyObject *
|
PyObject *
|
||||||
lookup_maybe(PyObject *self, _Py_Identifier *attrid)
|
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
|
||||||
{
|
{
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
|
|
||||||
|
@ -1471,12 +1465,6 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
|
||||||
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
|
|
||||||
{
|
|
||||||
return lookup_maybe(self, attrid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
call_unbound(int unbound, PyObject *func, PyObject *self,
|
call_unbound(int unbound, PyObject *func, PyObject *self,
|
||||||
PyObject **args, Py_ssize_t nargs)
|
PyObject **args, Py_ssize_t nargs)
|
||||||
|
@ -1501,9 +1489,8 @@ call_unbound_noarg(int unbound, PyObject *func, PyObject *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A variation of PyObject_CallMethodObjArgs that uses lookup_maybe_method()
|
/* A variation of PyObject_CallMethod* that uses lookup_maybe_method()
|
||||||
instead of PyObject_GetAttrString(). This uses the same convention
|
instead of PyObject_GetAttrString(). */
|
||||||
as lookup_maybe_method to cache the interned name string object. */
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
call_method(PyObject *obj, _Py_Identifier *name,
|
call_method(PyObject *obj, _Py_Identifier *name,
|
||||||
PyObject **args, Py_ssize_t nargs)
|
PyObject **args, Py_ssize_t nargs)
|
||||||
|
@ -1511,13 +1498,10 @@ call_method(PyObject *obj, _Py_Identifier *name,
|
||||||
int unbound;
|
int unbound;
|
||||||
PyObject *func, *retval;
|
PyObject *func, *retval;
|
||||||
|
|
||||||
func = lookup_maybe_method(obj, name, &unbound);
|
func = lookup_method(obj, name, &unbound);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
if (!PyErr_Occurred())
|
|
||||||
PyErr_SetObject(PyExc_AttributeError, name->object);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = call_unbound(unbound, func, obj, args, nargs);
|
retval = call_unbound(unbound, func, obj, args, nargs);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -5960,45 +5944,19 @@ slot_sq_length(PyObject *self)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Super-optimized version of slot_sq_item.
|
|
||||||
Other slots could do the same... */
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
slot_sq_item(PyObject *self, Py_ssize_t i)
|
slot_sq_item(PyObject *self, Py_ssize_t i)
|
||||||
{
|
{
|
||||||
PyObject *func, *ival = NULL, *retval = NULL;
|
PyObject *retval;
|
||||||
descrgetfunc f;
|
PyObject *args[1];
|
||||||
|
PyObject *ival = PyLong_FromSsize_t(i);
|
||||||
func = _PyType_LookupId(Py_TYPE(self), &PyId___getitem__);
|
if (ival == NULL) {
|
||||||
if (func == NULL) {
|
|
||||||
PyObject *getitem_str = _PyUnicode_FromId(&PyId___getitem__);
|
|
||||||
PyErr_SetObject(PyExc_AttributeError, getitem_str);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
args[0] = ival;
|
||||||
f = Py_TYPE(func)->tp_descr_get;
|
retval = call_method(self, &PyId___getitem__, args, 1);
|
||||||
if (f == NULL) {
|
|
||||||
Py_INCREF(func);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
func = f(func, self, (PyObject *)(Py_TYPE(self)));
|
|
||||||
if (func == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ival = PyLong_FromSsize_t(i);
|
|
||||||
if (ival == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = PyObject_CallFunctionObjArgs(func, ival, NULL);
|
|
||||||
Py_DECREF(func);
|
|
||||||
Py_DECREF(ival);
|
Py_DECREF(ival);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
error:
|
|
||||||
Py_DECREF(func);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -6223,7 +6181,7 @@ slot_tp_repr(PyObject *self)
|
||||||
_Py_IDENTIFIER(__repr__);
|
_Py_IDENTIFIER(__repr__);
|
||||||
int unbound;
|
int unbound;
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___repr__, &unbound);
|
func = lookup_maybe_method(self, &PyId___repr__, &unbound);
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
res = call_unbound_noarg(unbound, func, self);
|
res = call_unbound_noarg(unbound, func, self);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -6243,7 +6201,7 @@ slot_tp_hash(PyObject *self)
|
||||||
Py_ssize_t h;
|
Py_ssize_t h;
|
||||||
int unbound;
|
int unbound;
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___hash__, &unbound);
|
func = lookup_maybe_method(self, &PyId___hash__, &unbound);
|
||||||
|
|
||||||
if (func == Py_None) {
|
if (func == Py_None) {
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -6422,7 +6380,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
int unbound;
|
int unbound;
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
|
|
||||||
func = lookup_method(self, &name_op[op], &unbound);
|
func = lookup_maybe_method(self, &name_op[op], &unbound);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
Py_RETURN_NOTIMPLEMENTED;
|
||||||
|
@ -6441,7 +6399,7 @@ slot_tp_iter(PyObject *self)
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
_Py_IDENTIFIER(__iter__);
|
_Py_IDENTIFIER(__iter__);
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___iter__, &unbound);
|
func = lookup_maybe_method(self, &PyId___iter__, &unbound);
|
||||||
if (func == Py_None) {
|
if (func == Py_None) {
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
@ -6457,7 +6415,7 @@ slot_tp_iter(PyObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
func = lookup_method(self, &PyId___getitem__, &unbound);
|
func = lookup_maybe_method(self, &PyId___getitem__, &unbound);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"'%.200s' object is not iterable",
|
"'%.200s' object is not iterable",
|
||||||
|
@ -6597,7 +6555,7 @@ slot_am_await(PyObject *self)
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
_Py_IDENTIFIER(__await__);
|
_Py_IDENTIFIER(__await__);
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___await__, &unbound);
|
func = lookup_maybe_method(self, &PyId___await__, &unbound);
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
res = call_unbound_noarg(unbound, func, self);
|
res = call_unbound_noarg(unbound, func, self);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -6616,7 +6574,7 @@ slot_am_aiter(PyObject *self)
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
_Py_IDENTIFIER(__aiter__);
|
_Py_IDENTIFIER(__aiter__);
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___aiter__, &unbound);
|
func = lookup_maybe_method(self, &PyId___aiter__, &unbound);
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
res = call_unbound_noarg(unbound, func, self);
|
res = call_unbound_noarg(unbound, func, self);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -6635,7 +6593,7 @@ slot_am_anext(PyObject *self)
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
_Py_IDENTIFIER(__anext__);
|
_Py_IDENTIFIER(__anext__);
|
||||||
|
|
||||||
func = lookup_method(self, &PyId___anext__, &unbound);
|
func = lookup_maybe_method(self, &PyId___anext__, &unbound);
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
res = call_unbound_noarg(unbound, func, self);
|
res = call_unbound_noarg(unbound, func, self);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
|
@ -7182,7 +7140,7 @@ set_names(PyTypeObject *type)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (PyDict_Next(names_to_set, &i, &key, &value)) {
|
while (PyDict_Next(names_to_set, &i, &key, &value)) {
|
||||||
set_name = lookup_maybe(value, &PyId___set_name__);
|
set_name = _PyObject_LookupSpecial(value, &PyId___set_name__);
|
||||||
if (set_name != NULL) {
|
if (set_name != NULL) {
|
||||||
tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL);
|
tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL);
|
||||||
Py_DECREF(set_name);
|
Py_DECREF(set_name);
|
||||||
|
|
Loading…
Reference in New Issue