mirror of https://github.com/python/cpython
bpo-47067: Optimize calling GenericAlias objects (GH-31996)
Use vectorcall, and replace `PyObject_SetAttrString` with `PyObject_SetAttr` and a global string.
This commit is contained in:
parent
5c3201e146
commit
1ea055bd53
|
@ -156,6 +156,7 @@ struct _Py_global_strings {
|
|||
STRUCT_FOR_ID(__next__)
|
||||
STRUCT_FOR_ID(__note__)
|
||||
STRUCT_FOR_ID(__or__)
|
||||
STRUCT_FOR_ID(__orig_class__)
|
||||
STRUCT_FOR_ID(__origin__)
|
||||
STRUCT_FOR_ID(__package__)
|
||||
STRUCT_FOR_ID(__parameters__)
|
||||
|
|
|
@ -779,6 +779,7 @@ extern "C" {
|
|||
INIT_ID(__next__), \
|
||||
INIT_ID(__note__), \
|
||||
INIT_ID(__or__), \
|
||||
INIT_ID(__orig_class__), \
|
||||
INIT_ID(__origin__), \
|
||||
INIT_ID(__package__), \
|
||||
INIT_ID(__parameters__), \
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Optimize calling ``GenericAlias`` objects by using :pep:`590` ``vectorcall`` and by replacing ``PyObject_SetAttrString`` with ``PyObject_SetAttr``.
|
|
@ -12,9 +12,10 @@ typedef struct {
|
|||
PyObject *origin;
|
||||
PyObject *args;
|
||||
PyObject *parameters;
|
||||
PyObject* weakreflist;
|
||||
PyObject *weakreflist;
|
||||
// Whether we're a starred type, e.g. *tuple[int].
|
||||
bool starred;
|
||||
vectorcallfunc vectorcall;
|
||||
} gaobject;
|
||||
|
||||
typedef struct {
|
||||
|
@ -383,13 +384,11 @@ ga_hash(PyObject *self)
|
|||
return h0 ^ h1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
ga_call(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
static inline PyObject *
|
||||
set_orig_class(PyObject *obj, PyObject *self)
|
||||
{
|
||||
gaobject *alias = (gaobject *)self;
|
||||
PyObject *obj = PyObject_Call(alias->origin, args, kwds);
|
||||
if (obj != NULL) {
|
||||
if (PyObject_SetAttrString(obj, "__orig_class__", self) < 0) {
|
||||
if (PyObject_SetAttr(obj, &_Py_ID(__orig_class__), self) < 0) {
|
||||
if (!PyErr_ExceptionMatches(PyExc_AttributeError) &&
|
||||
!PyErr_ExceptionMatches(PyExc_TypeError))
|
||||
{
|
||||
|
@ -402,6 +401,23 @@ ga_call(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return obj;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
ga_call(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
gaobject *alias = (gaobject *)self;
|
||||
PyObject *obj = PyObject_Call(alias->origin, args, kwds);
|
||||
return set_orig_class(obj, self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
ga_vectorcall(PyObject *self, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
gaobject *alias = (gaobject *) self;
|
||||
PyObject *obj = PyVectorcall_Function(alias->origin)(alias->origin, args, nargsf, kwnames);
|
||||
return set_orig_class(obj, self);
|
||||
}
|
||||
|
||||
static const char* const attr_exceptions[] = {
|
||||
"__origin__",
|
||||
"__args__",
|
||||
|
@ -588,6 +604,14 @@ setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
|
|||
alias->args = args;
|
||||
alias->parameters = NULL;
|
||||
alias->weakreflist = NULL;
|
||||
|
||||
if (PyVectorcall_Function(origin) != NULL) {
|
||||
alias->vectorcall = ga_vectorcall;
|
||||
}
|
||||
else {
|
||||
alias->vectorcall = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -695,7 +719,7 @@ PyTypeObject Py_GenericAliasType = {
|
|||
.tp_hash = ga_hash,
|
||||
.tp_call = ga_call,
|
||||
.tp_getattro = ga_getattro,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL,
|
||||
.tp_traverse = ga_traverse,
|
||||
.tp_richcompare = ga_richcompare,
|
||||
.tp_weaklistoffset = offsetof(gaobject, weakreflist),
|
||||
|
@ -706,6 +730,7 @@ PyTypeObject Py_GenericAliasType = {
|
|||
.tp_free = PyObject_GC_Del,
|
||||
.tp_getset = ga_properties,
|
||||
.tp_iter = (getiterfunc)ga_iter,
|
||||
.tp_vectorcall_offset = offsetof(gaobject, vectorcall),
|
||||
};
|
||||
|
||||
PyObject *
|
||||
|
|
Loading…
Reference in New Issue