summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpenguin_wwy <940375606@qq.com>2022-03-21 20:33:02 (GMT)
committerGitHub <noreply@github.com>2022-03-21 20:33:02 (GMT)
commit1ea055bd53ccf976e88018983a3c13447c4502be (patch)
treeb2c6e4d3b1f9db90c7b45eb6b69c8c6d20bda606
parent5c3201e146b251017cd77202015f47912ddcb980 (diff)
downloadcpython-1ea055bd53ccf976e88018983a3c13447c4502be.zip
cpython-1ea055bd53ccf976e88018983a3c13447c4502be.tar.gz
cpython-1ea055bd53ccf976e88018983a3c13447c4502be.tar.bz2
bpo-47067: Optimize calling GenericAlias objects (GH-31996)
Use vectorcall, and replace `PyObject_SetAttrString` with `PyObject_SetAttr` and a global string.
-rw-r--r--Include/internal/pycore_global_strings.h1
-rw-r--r--Include/internal/pycore_runtime_init.h1
-rw-r--r--Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst1
-rw-r--r--Objects/genericaliasobject.c39
4 files changed, 35 insertions, 7 deletions
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index 35bffa7..1d83bf2 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -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__)
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 20d543a..d5690d8 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -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__), \
diff --git a/Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst b/Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst
new file mode 100644
index 0000000..28c0895
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst
@@ -0,0 +1 @@
+Optimize calling ``GenericAlias`` objects by using :pep:`590` ``vectorcall`` and by replacing ``PyObject_SetAttrString`` with ``PyObject_SetAttr``.
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 224a2e9..3f03630 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -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 *