diff options
author | Carl Meyer <carl@oddbird.net> | 2023-04-25 17:45:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-25 17:45:51 (GMT) |
commit | ef25febcf2ede92a03c5ea00a13e167e0b5cb274 (patch) | |
tree | 6ce38cd3aa3d653d931df5250b02b5cb6b46bb69 /Objects | |
parent | cef542ca572fdd402ff0e10093a0c1b459e5dcd6 (diff) | |
download | cpython-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.c | 84 |
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) { |