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:
penguin_wwy 2022-03-22 04:33:02 +08:00 committed by GitHub
parent 5c3201e146
commit 1ea055bd53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 7 deletions

View File

@ -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__)

View File

@ -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__), \

View File

@ -0,0 +1 @@
Optimize calling ``GenericAlias`` objects by using :pep:`590` ``vectorcall`` and by replacing ``PyObject_SetAttrString`` with ``PyObject_SetAttr``.

View File

@ -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 *