Skip to content

Commit 4e624ca

Browse files
bpo-30509: Clean up calling type slots. (#1883)
Also speed up slot_sq_item.
1 parent 56ddfd2 commit 4e624ca

File tree

1 file changed

+26
-68
lines changed

1 file changed

+26
-68
lines changed

Objects/typeobject.c

Lines changed: 26 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,29 +1398,23 @@ PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
13981398
return type_is_subtype_base_chain(a, b);
13991399
}
14001400

1401-
/* Internal routines to do a method lookup in the type
1402-
without looking in the instance dictionary
1403-
(so we can't use PyObject_GetAttr) but still binding
1404-
it to the instance. The arguments are the object,
1405-
the method name as a C string, and the address of a
1406-
static variable used to cache the interned Python string.
1401+
/* Routines to do a method lookup in the type without looking in the
1402+
instance dictionary (so we can't use PyObject_GetAttr) but still
1403+
binding it to the instance.
14071404
14081405
Variants:
14091406
1410-
- lookup_maybe() returns NULL without raising an exception
1407+
- _PyObject_LookupSpecial() returns NULL without raising an exception
14111408
when the _PyType_Lookup() call fails;
14121409
1413-
- lookup_maybe_method() and lookup_method() are similar to
1414-
lookup_maybe(), but can return unbound PyFunction
1410+
- lookup_maybe_method() and lookup_method() are internal routines similar
1411+
to _PyObject_LookupSpecial(), but can return unbound PyFunction
14151412
to avoid temporary method object. Pass self as first argument when
14161413
unbound == 1.
1417-
1418-
- _PyObject_LookupSpecial() expose lookup_maybe for the benefit of
1419-
other places.
14201414
*/
14211415

1422-
static PyObject *
1423-
lookup_maybe(PyObject *self, _Py_Identifier *attrid)
1416+
PyObject *
1417+
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
14241418
{
14251419
PyObject *res;
14261420

@@ -1471,12 +1465,6 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
14711465
return res;
14721466
}
14731467

1474-
PyObject *
1475-
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
1476-
{
1477-
return lookup_maybe(self, attrid);
1478-
}
1479-
14801468
static PyObject*
14811469
call_unbound(int unbound, PyObject *func, PyObject *self,
14821470
PyObject **args, Py_ssize_t nargs)
@@ -1501,23 +1489,19 @@ call_unbound_noarg(int unbound, PyObject *func, PyObject *self)
15011489
}
15021490
}
15031491

1504-
/* A variation of PyObject_CallMethodObjArgs that uses lookup_maybe_method()
1505-
instead of PyObject_GetAttrString(). This uses the same convention
1506-
as lookup_maybe_method to cache the interned name string object. */
1492+
/* A variation of PyObject_CallMethod* that uses lookup_maybe_method()
1493+
instead of PyObject_GetAttrString(). */
15071494
static PyObject *
15081495
call_method(PyObject *obj, _Py_Identifier *name,
15091496
PyObject **args, Py_ssize_t nargs)
15101497
{
15111498
int unbound;
15121499
PyObject *func, *retval;
15131500

1514-
func = lookup_maybe_method(obj, name, &unbound);
1501+
func = lookup_method(obj, name, &unbound);
15151502
if (func == NULL) {
1516-
if (!PyErr_Occurred())
1517-
PyErr_SetObject(PyExc_AttributeError, name->object);
15181503
return NULL;
15191504
}
1520-
15211505
retval = call_unbound(unbound, func, obj, args, nargs);
15221506
Py_DECREF(func);
15231507
return retval;
@@ -5960,45 +5944,19 @@ slot_sq_length(PyObject *self)
59605944
return len;
59615945
}
59625946

5963-
/* Super-optimized version of slot_sq_item.
5964-
Other slots could do the same... */
59655947
static PyObject *
59665948
slot_sq_item(PyObject *self, Py_ssize_t i)
59675949
{
5968-
PyObject *func, *ival = NULL, *retval = NULL;
5969-
descrgetfunc f;
5970-
5971-
func = _PyType_LookupId(Py_TYPE(self), &PyId___getitem__);
5972-
if (func == NULL) {
5973-
PyObject *getitem_str = _PyUnicode_FromId(&PyId___getitem__);
5974-
PyErr_SetObject(PyExc_AttributeError, getitem_str);
5975-
return NULL;
5976-
}
5977-
5978-
f = Py_TYPE(func)->tp_descr_get;
5979-
if (f == NULL) {
5980-
Py_INCREF(func);
5981-
}
5982-
else {
5983-
func = f(func, self, (PyObject *)(Py_TYPE(self)));
5984-
if (func == NULL) {
5985-
return NULL;
5986-
}
5987-
}
5988-
5989-
ival = PyLong_FromSsize_t(i);
5950+
PyObject *retval;
5951+
PyObject *args[1];
5952+
PyObject *ival = PyLong_FromSsize_t(i);
59905953
if (ival == NULL) {
5991-
goto error;
5954+
return NULL;
59925955
}
5993-
5994-
retval = PyObject_CallFunctionObjArgs(func, ival, NULL);
5995-
Py_DECREF(func);
5956+
args[0] = ival;
5957+
retval = call_method(self, &PyId___getitem__, args, 1);
59965958
Py_DECREF(ival);
59975959
return retval;
5998-
5999-
error:
6000-
Py_DECREF(func);
6001-
return NULL;
60025960
}
60035961

60045962
static int
@@ -6223,7 +6181,7 @@ slot_tp_repr(PyObject *self)
62236181
_Py_IDENTIFIER(__repr__);
62246182
int unbound;
62256183

6226-
func = lookup_method(self, &PyId___repr__, &unbound);
6184+
func = lookup_maybe_method(self, &PyId___repr__, &unbound);
62276185
if (func != NULL) {
62286186
res = call_unbound_noarg(unbound, func, self);
62296187
Py_DECREF(func);
@@ -6243,7 +6201,7 @@ slot_tp_hash(PyObject *self)
62436201
Py_ssize_t h;
62446202
int unbound;
62456203

6246-
func = lookup_method(self, &PyId___hash__, &unbound);
6204+
func = lookup_maybe_method(self, &PyId___hash__, &unbound);
62476205

62486206
if (func == Py_None) {
62496207
Py_DECREF(func);
@@ -6422,7 +6380,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
64226380
int unbound;
64236381
PyObject *func, *res;
64246382

6425-
func = lookup_method(self, &name_op[op], &unbound);
6383+
func = lookup_maybe_method(self, &name_op[op], &unbound);
64266384
if (func == NULL) {
64276385
PyErr_Clear();
64286386
Py_RETURN_NOTIMPLEMENTED;
@@ -6441,7 +6399,7 @@ slot_tp_iter(PyObject *self)
64416399
PyObject *func, *res;
64426400
_Py_IDENTIFIER(__iter__);
64436401

6444-
func = lookup_method(self, &PyId___iter__, &unbound);
6402+
func = lookup_maybe_method(self, &PyId___iter__, &unbound);
64456403
if (func == Py_None) {
64466404
Py_DECREF(func);
64476405
PyErr_Format(PyExc_TypeError,
@@ -6457,7 +6415,7 @@ slot_tp_iter(PyObject *self)
64576415
}
64586416

64596417
PyErr_Clear();
6460-
func = lookup_method(self, &PyId___getitem__, &unbound);
6418+
func = lookup_maybe_method(self, &PyId___getitem__, &unbound);
64616419
if (func == NULL) {
64626420
PyErr_Format(PyExc_TypeError,
64636421
"'%.200s' object is not iterable",
@@ -6597,7 +6555,7 @@ slot_am_await(PyObject *self)
65976555
PyObject *func, *res;
65986556
_Py_IDENTIFIER(__await__);
65996557

6600-
func = lookup_method(self, &PyId___await__, &unbound);
6558+
func = lookup_maybe_method(self, &PyId___await__, &unbound);
66016559
if (func != NULL) {
66026560
res = call_unbound_noarg(unbound, func, self);
66036561
Py_DECREF(func);
@@ -6616,7 +6574,7 @@ slot_am_aiter(PyObject *self)
66166574
PyObject *func, *res;
66176575
_Py_IDENTIFIER(__aiter__);
66186576

6619-
func = lookup_method(self, &PyId___aiter__, &unbound);
6577+
func = lookup_maybe_method(self, &PyId___aiter__, &unbound);
66206578
if (func != NULL) {
66216579
res = call_unbound_noarg(unbound, func, self);
66226580
Py_DECREF(func);
@@ -6635,7 +6593,7 @@ slot_am_anext(PyObject *self)
66356593
PyObject *func, *res;
66366594
_Py_IDENTIFIER(__anext__);
66376595

6638-
func = lookup_method(self, &PyId___anext__, &unbound);
6596+
func = lookup_maybe_method(self, &PyId___anext__, &unbound);
66396597
if (func != NULL) {
66406598
res = call_unbound_noarg(unbound, func, self);
66416599
Py_DECREF(func);
@@ -7182,7 +7140,7 @@ set_names(PyTypeObject *type)
71827140
return -1;
71837141

71847142
while (PyDict_Next(names_to_set, &i, &key, &value)) {
7185-
set_name = lookup_maybe(value, &PyId___set_name__);
7143+
set_name = _PyObject_LookupSpecial(value, &PyId___set_name__);
71867144
if (set_name != NULL) {
71877145
tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL);
71887146
Py_DECREF(set_name);

0 commit comments

Comments
 (0)