Skip to content

gh-75646: allow _PyType_Lookup() to raise exceptions #3616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0a865c9
Speed up type creation, which is highly dominated by slow dict lookups.
Sep 4, 2017
c4779e3
Update comment after changing the function call that it refers to.
Sep 4, 2017
ff2ea63
Ignore any errors (however unlikely) that may happen during the mro c…
Sep 4, 2017
76b1986
Extract non-caching code from _PyType_Lookup() to use it directly fro…
Sep 5, 2017
6f98485
Avoid some useless overhead for the no-basetype case. If "object" eve…
Sep 5, 2017
d9b726e
Add comment.
Sep 6, 2017
be15255
Avoid uselessly searching empty bases for a metaclass. This is quite …
Sep 6, 2017
0736226
Avoid unsafe handling of borrowed "mro" reference during hash() call.
Sep 10, 2017
8bc783f
Clean up code and formatting a little.
Sep 10, 2017
66648dd
Add braces for code style reasons.
Sep 10, 2017
85fb3ae
Give internal helper function a local name that does not resemble (ex…
Sep 10, 2017
09e716a
Allow non-dict types for the class dict when looking up names and cal…
Sep 11, 2017
1d52082
Lazily calculate name hash in find_name_in_mro() to avoid potential r…
Sep 11, 2017
f09bfd3
Revert "Lazily calculate name hash in find_name_in_mro() to avoid pot…
Sep 11, 2017
824d7cb
Revert "Allow non-dict types for the class dict when looking up names…
Sep 11, 2017
5184191
add news entry for faster class creation
Sep 13, 2017
4efde8e
Change nice interface of "find_name_in_mro()" to evil interface eatin…
Sep 13, 2017
f5bce2a
Mention amount of speedup in News entry.
Sep 13, 2017
02bfef0
Revert "Change nice interface of "find_name_in_mro()" to evil interfa…
Sep 14, 2017
2497858
Guard against external live exceptions when calling find_name_in_mro(…
Sep 14, 2017
c56990d
Merge branch 'master' into _pt_lookup_exc
Sep 15, 2017
6c61028
Propagate exception when _PyObject_LookupSpecial() fails (as done eve…
Sep 14, 2017
1b5950f
Allow _PyType_Lookup() and _PyType_LookupId() to raise exceptions and…
Sep 15, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ PyAPI_FUNC(PyObject *) PyType_GenericAlloc(PyTypeObject *, Py_ssize_t);
PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
PyObject *, PyObject *);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *);
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *, int *);
PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *, int *);
PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up class creation by 10-20% by reducing the overhead in the
necessary special method lookups. Patch by Stefan Behnel.
21 changes: 17 additions & 4 deletions Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2257,6 +2257,7 @@ _count_elements(PyObject *self, PyObject *args)
PyObject *dict_get;
PyObject *mapping_setitem;
PyObject *dict_setitem;
int error;

if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
return NULL;
Expand All @@ -2268,10 +2269,22 @@ _count_elements(PyObject *self, PyObject *args)
/* Only take the fast path when get() and __setitem__()
* have not been overridden.
*/
mapping_get = _PyType_LookupId(Py_TYPE(mapping), &PyId_get);
dict_get = _PyType_LookupId(&PyDict_Type, &PyId_get);
mapping_setitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___setitem__);
dict_setitem = _PyType_LookupId(&PyDict_Type, &PyId___setitem__);
mapping_get = _PyType_LookupId(Py_TYPE(mapping), &PyId_get, &error);
if (error == -1) {
goto done;
}
dict_get = _PyType_LookupId(&PyDict_Type, &PyId_get, &error);
if (error == -1) {
goto done;
}
mapping_setitem = _PyType_LookupId(Py_TYPE(mapping), &PyId___setitem__, &error);
if (error == -1) {
goto done;
}
dict_setitem = _PyType_LookupId(&PyDict_Type, &PyId___setitem__, &error);
if (error == -1) {
goto done;
}

if (mapping_get != NULL && mapping_get == dict_get &&
mapping_setitem != NULL && mapping_setitem == dict_setitem) {
Expand Down
3 changes: 2 additions & 1 deletion Modules/_lsprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,10 @@ normalizeUserObj(PyObject *obj)
PyObject *self = fn->m_self;
PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name);
PyObject *modname = fn->m_module;
int ignore;

if (name != NULL) {
PyObject *mo = _PyType_Lookup(Py_TYPE(self), name);
PyObject *mo = _PyType_Lookup(Py_TYPE(self), name, &ignore);
Py_XINCREF(mo);
Py_DECREF(name);
if (mo != NULL) {
Expand Down
2 changes: 2 additions & 0 deletions Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen)
*pbuf = PyBytes_AS_STRING(result);
*plen = PyBytes_GET_SIZE(result);
return result;
} else if (PyErr_Occurred()) {
return NULL;
}
/* does it support buffer protocol? */
if (PyObject_CheckBuffer(v)) {
Expand Down
10 changes: 8 additions & 2 deletions Objects/classobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,14 @@ method_getattro(PyObject *obj, PyObject *name)
PyMethodObject *im = (PyMethodObject *)obj;
PyTypeObject *tp = obj->ob_type;
PyObject *descr = NULL;
int error;

{
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
descr = _PyType_Lookup(tp, name, &error);
}

if (descr != NULL) {
Expand All @@ -155,6 +156,8 @@ method_getattro(PyObject *obj, PyObject *name)
Py_INCREF(descr);
return descr;
}
} else if (error == -1) {
return NULL;
}

return PyObject_GetAttr(im->im_func, name);
Expand Down Expand Up @@ -462,12 +465,13 @@ instancemethod_getattro(PyObject *self, PyObject *name)
{
PyTypeObject *tp = self->ob_type;
PyObject *descr = NULL;
int error;

if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
descr = _PyType_Lookup(tp, name, &error);

if (descr != NULL) {
descrgetfunc f = TP_DESCR_GET(descr->ob_type);
Expand All @@ -477,6 +481,8 @@ instancemethod_getattro(PyObject *self, PyObject *name)
Py_INCREF(descr);
return descr;
}
} else if (error == -1) {
return NULL;
}

return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name);
Expand Down
15 changes: 12 additions & 3 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
PyObject **dictptr, *dict;
PyObject *attr;
int meth_found = 0;
int error;

assert(*method == NULL);

Expand All @@ -1055,7 +1056,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
if (tp->tp_dict == NULL && PyType_Ready(tp) < 0)
return 0;

descr = _PyType_Lookup(tp, name);
descr = _PyType_Lookup(tp, name, &error);
if (descr != NULL) {
Py_INCREF(descr);
if (PyFunction_Check(descr) ||
Expand All @@ -1069,6 +1070,8 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
return 0;
}
}
} else if (error == -1) {
return 0;
}

dictptr = _PyObject_GetDictPtr(obj);
Expand Down Expand Up @@ -1122,6 +1125,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
descrgetfunc f;
Py_ssize_t dictoffset;
PyObject **dictptr;
int error;

if (!PyUnicode_Check(name)){
PyErr_Format(PyExc_TypeError,
Expand All @@ -1136,7 +1140,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
goto done;
}

descr = _PyType_Lookup(tp, name);
descr = _PyType_Lookup(tp, name, &error);

f = NULL;
if (descr != NULL) {
Expand All @@ -1146,6 +1150,8 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
res = f(descr, obj, (PyObject *)obj->ob_type);
goto done;
}
} else if (error == -1) {
goto done;
}

if (dict == NULL) {
Expand Down Expand Up @@ -1216,6 +1222,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
descrsetfunc f;
PyObject **dictptr;
int res = -1;
int error;

if (!PyUnicode_Check(name)){
PyErr_Format(PyExc_TypeError,
Expand All @@ -1229,7 +1236,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,

Py_INCREF(name);

descr = _PyType_Lookup(tp, name);
descr = _PyType_Lookup(tp, name, &error);

if (descr != NULL) {
Py_INCREF(descr);
Expand All @@ -1238,6 +1245,8 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
res = f(descr, obj, value);
goto done;
}
} else if (error == -1) {
goto done;
}

if (dict == NULL) {
Expand Down
Loading