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(__next__)
|
||||||
STRUCT_FOR_ID(__note__)
|
STRUCT_FOR_ID(__note__)
|
||||||
STRUCT_FOR_ID(__or__)
|
STRUCT_FOR_ID(__or__)
|
||||||
|
STRUCT_FOR_ID(__orig_class__)
|
||||||
STRUCT_FOR_ID(__origin__)
|
STRUCT_FOR_ID(__origin__)
|
||||||
STRUCT_FOR_ID(__package__)
|
STRUCT_FOR_ID(__package__)
|
||||||
STRUCT_FOR_ID(__parameters__)
|
STRUCT_FOR_ID(__parameters__)
|
||||||
|
|
|
@ -779,6 +779,7 @@ extern "C" {
|
||||||
INIT_ID(__next__), \
|
INIT_ID(__next__), \
|
||||||
INIT_ID(__note__), \
|
INIT_ID(__note__), \
|
||||||
INIT_ID(__or__), \
|
INIT_ID(__or__), \
|
||||||
|
INIT_ID(__orig_class__), \
|
||||||
INIT_ID(__origin__), \
|
INIT_ID(__origin__), \
|
||||||
INIT_ID(__package__), \
|
INIT_ID(__package__), \
|
||||||
INIT_ID(__parameters__), \
|
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 *origin;
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
PyObject *parameters;
|
PyObject *parameters;
|
||||||
PyObject* weakreflist;
|
PyObject *weakreflist;
|
||||||
// Whether we're a starred type, e.g. *tuple[int].
|
// Whether we're a starred type, e.g. *tuple[int].
|
||||||
bool starred;
|
bool starred;
|
||||||
|
vectorcallfunc vectorcall;
|
||||||
} gaobject;
|
} gaobject;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -383,13 +384,11 @@ ga_hash(PyObject *self)
|
||||||
return h0 ^ h1;
|
return h0 ^ h1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static inline PyObject *
|
||||||
ga_call(PyObject *self, PyObject *args, PyObject *kwds)
|
set_orig_class(PyObject *obj, PyObject *self)
|
||||||
{
|
{
|
||||||
gaobject *alias = (gaobject *)self;
|
|
||||||
PyObject *obj = PyObject_Call(alias->origin, args, kwds);
|
|
||||||
if (obj != NULL) {
|
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) &&
|
if (!PyErr_ExceptionMatches(PyExc_AttributeError) &&
|
||||||
!PyErr_ExceptionMatches(PyExc_TypeError))
|
!PyErr_ExceptionMatches(PyExc_TypeError))
|
||||||
{
|
{
|
||||||
|
@ -402,6 +401,23 @@ ga_call(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return obj;
|
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[] = {
|
static const char* const attr_exceptions[] = {
|
||||||
"__origin__",
|
"__origin__",
|
||||||
"__args__",
|
"__args__",
|
||||||
|
@ -588,6 +604,14 @@ setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
|
||||||
alias->args = args;
|
alias->args = args;
|
||||||
alias->parameters = NULL;
|
alias->parameters = NULL;
|
||||||
alias->weakreflist = NULL;
|
alias->weakreflist = NULL;
|
||||||
|
|
||||||
|
if (PyVectorcall_Function(origin) != NULL) {
|
||||||
|
alias->vectorcall = ga_vectorcall;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alias->vectorcall = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,7 +719,7 @@ PyTypeObject Py_GenericAliasType = {
|
||||||
.tp_hash = ga_hash,
|
.tp_hash = ga_hash,
|
||||||
.tp_call = ga_call,
|
.tp_call = ga_call,
|
||||||
.tp_getattro = ga_getattro,
|
.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_traverse = ga_traverse,
|
||||||
.tp_richcompare = ga_richcompare,
|
.tp_richcompare = ga_richcompare,
|
||||||
.tp_weaklistoffset = offsetof(gaobject, weakreflist),
|
.tp_weaklistoffset = offsetof(gaobject, weakreflist),
|
||||||
|
@ -706,6 +730,7 @@ PyTypeObject Py_GenericAliasType = {
|
||||||
.tp_free = PyObject_GC_Del,
|
.tp_free = PyObject_GC_Del,
|
||||||
.tp_getset = ga_properties,
|
.tp_getset = ga_properties,
|
||||||
.tp_iter = (getiterfunc)ga_iter,
|
.tp_iter = (getiterfunc)ga_iter,
|
||||||
|
.tp_vectorcall_offset = offsetof(gaobject, vectorcall),
|
||||||
};
|
};
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
Loading…
Reference in New Issue