summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-04-25 17:45:51 (GMT)
committerGitHub <noreply@github.com>2023-04-25 17:45:51 (GMT)
commitef25febcf2ede92a03c5ea00a13e167e0b5cb274 (patch)
tree6ce38cd3aa3d653d931df5250b02b5cb6b46bb69 /Objects
parentcef542ca572fdd402ff0e10093a0c1b459e5dcd6 (diff)
downloadcpython-ef25febcf2ede92a03c5ea00a13e167e0b5cb274.zip
cpython-ef25febcf2ede92a03c5ea00a13e167e0b5cb274.tar.gz
cpython-ef25febcf2ede92a03c5ea00a13e167e0b5cb274.tar.bz2
gh-87729: specialize LOAD_SUPER_ATTR_METHOD (#103809)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c84
1 files changed, 58 insertions, 26 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 09ea566..9194eba 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -9380,22 +9380,19 @@ super_repr(PyObject *self)
su->type ? su->type->tp_name : "NULL");
}
-// if `method` is non-NULL, we are looking for a method descriptor,
-// and setting `*method` to 1 means we found one.
+/* Do a super lookup without executing descriptors or falling back to getattr
+on the super object itself.
+
+May return NULL with or without an exception set, like PyDict_GetItemWithError. */
static PyObject *
-do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
- PyTypeObject *su_obj_type, PyObject *name, int *method)
+_super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject *name)
{
PyObject *mro, *res;
Py_ssize_t i, n;
- int temp_su = 0;
-
- if (su_obj_type == NULL)
- goto skip;
mro = su_obj_type->tp_mro;
if (mro == NULL)
- goto skip;
+ return NULL;
assert(PyTuple_Check(mro));
n = PyTuple_GET_SIZE(mro);
@@ -9407,7 +9404,7 @@ do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
}
i++; /* skip su->type (if any) */
if (i >= n)
- goto skip;
+ return NULL;
/* keep a strong reference to mro because su_obj_type->tp_mro can be
replaced during PyDict_GetItemWithError(dict, name) */
@@ -9420,22 +9417,6 @@ do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
res = PyDict_GetItemWithError(dict, name);
if (res != NULL) {
Py_INCREF(res);
- if (method && _PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
- *method = 1;
- }
- else {
- descrgetfunc f = Py_TYPE(res)->tp_descr_get;
- if (f != NULL) {
- PyObject *res2;
- res2 = f(res,
- /* Only pass 'obj' param if this is instance-mode super
- (See SF ID #743627) */
- (su_obj == (PyObject *)su_obj_type) ? NULL : su_obj,
- (PyObject *)su_obj_type);
- Py_SETREF(res, res2);
- }
- }
-
Py_DECREF(mro);
return res;
}
@@ -9447,6 +9428,45 @@ do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
i++;
} while (i < n);
Py_DECREF(mro);
+ return NULL;
+}
+
+// if `method` is non-NULL, we are looking for a method descriptor,
+// and setting `*method = 1` means we found one.
+static PyObject *
+do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
+ PyTypeObject *su_obj_type, PyObject *name, int *method)
+{
+ PyObject *res;
+ int temp_su = 0;
+
+ if (su_obj_type == NULL) {
+ goto skip;
+ }
+
+ res = _super_lookup_descr(su_type, su_obj_type, name);
+ if (res != NULL) {
+ if (method && _PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
+ *method = 1;
+ }
+ else {
+ descrgetfunc f = Py_TYPE(res)->tp_descr_get;
+ if (f != NULL) {
+ PyObject *res2;
+ res2 = f(res,
+ /* Only pass 'obj' param if this is instance-mode super
+ (See SF ID #743627) */
+ (su_obj == (PyObject *)su_obj_type) ? NULL : su_obj,
+ (PyObject *)su_obj_type);
+ Py_SETREF(res, res2);
+ }
+ }
+
+ return res;
+ }
+ else if (PyErr_Occurred()) {
+ return NULL;
+ }
skip:
if (su == NULL) {
@@ -9544,6 +9564,18 @@ _PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *me
return res;
}
+PyObject *
+_PySuper_LookupDescr(PyTypeObject *su_type, PyObject *su_obj, PyObject *name)
+{
+ PyTypeObject *su_obj_type = supercheck(su_type, su_obj);
+ if (su_obj_type == NULL) {
+ return NULL;
+ }
+ PyObject *res = _super_lookup_descr(su_type, su_obj_type, name);
+ Py_DECREF(su_obj_type);
+ return res;
+}
+
static PyObject *
super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{