]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-47067: Optimize calling GenericAlias objects (GH-31996)
authorpenguin_wwy <940375606@qq.com>
Mon, 21 Mar 2022 20:33:02 +0000 (04:33 +0800)
committerGitHub <noreply@github.com>
Mon, 21 Mar 2022 20:33:02 +0000 (16:33 -0400)
Use vectorcall, and replace `PyObject_SetAttrString` with `PyObject_SetAttr` and a global string.

Include/internal/pycore_global_strings.h
Include/internal/pycore_runtime_init.h
Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst [new file with mode: 0644]
Objects/genericaliasobject.c

index 35bffa7aff949319f00185aca66c2feb3019d345..1d83bf2cfad4c729b1974318a2eb40c50cdb4c21 100644 (file)
@@ -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__)
index 20d543a8cbc565aa587966fec6cb2acc82eb3b3e..d5690d83a0482ba499c0b585e4ccd483354d7c7b 100644 (file)
@@ -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 (file)
index 0000000..28c0895
--- /dev/null
@@ -0,0 +1 @@
+Optimize calling ``GenericAlias`` objects by using :pep:`590` ``vectorcall`` and by replacing ``PyObject_SetAttrString`` with ``PyObject_SetAttr``.
index 224a2e9acb748e82a32a503a206e84f3ca14e07a..3f03630005bc5a2cf4bfa9d1376317e78bef5d18 100644 (file)
@@ -12,9 +12,10 @@ typedef struct {
     PyObject *origin;
     PyObject *args;
     PyObject *parameters;
-    PyObjectweakreflist;
+    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 *