gh-93274: Make vectorcall safe on mutable classes & inherit it by default (#95437)

This commit is contained in:
Petr Viktorin 2022-08-04 17:19:29 +02:00 committed by GitHub
parent a613fedd6e
commit 7b370b7305
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 351 additions and 21 deletions

View file

@ -6290,11 +6290,9 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
* won't be used automatically. */
COPYSLOT(tp_vectorcall_offset);
/* Inherit Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
* if tp_call is not overridden */
/* Inherit Py_TPFLAGS_HAVE_VECTORCALL if tp_call is not overridden */
if (!type->tp_call &&
_PyType_HasFeature(base, Py_TPFLAGS_HAVE_VECTORCALL) &&
_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE))
_PyType_HasFeature(base, Py_TPFLAGS_HAVE_VECTORCALL))
{
type->tp_flags |= Py_TPFLAGS_HAVE_VECTORCALL;
}
@ -8713,8 +8711,17 @@ update_one_slot(PyTypeObject *type, slotdef *p)
{
PyObject *descr;
PyWrapperDescrObject *d;
void *generic = NULL, *specific = NULL;
// The correct specialized C function, like "tp_repr of str" in the
// example above
void *specific = NULL;
// A generic wrapper that uses method lookup (safe but slow)
void *generic = NULL;
// Set to 1 if the generic wrapper is necessary
int use_generic = 0;
int offset = p->offset;
int error;
void **ptr = slotptr(type, offset);
@ -8797,6 +8804,10 @@ update_one_slot(PyTypeObject *type, slotdef *p)
else {
use_generic = 1;
generic = p->function;
if (p->function == slot_tp_call) {
/* A generic __call__ is incompatible with vectorcall */
type->tp_flags &= ~Py_TPFLAGS_HAVE_VECTORCALL;
}
}
} while ((++p)->offset == offset);
if (specific && !use_generic)