diff options
author | penguin_wwy <940375606@qq.com> | 2022-03-21 20:33:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-21 20:33:02 (GMT) |
commit | 1ea055bd53ccf976e88018983a3c13447c4502be (patch) | |
tree | b2c6e4d3b1f9db90c7b45eb6b69c8c6d20bda606 | |
parent | 5c3201e146b251017cd77202015f47912ddcb980 (diff) | |
download | cpython-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.h | 1 | ||||
-rw-r--r-- | Include/internal/pycore_runtime_init.h | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2022-03-20-17-15-56.bpo-47067.XXLnje.rst | 1 | ||||
-rw-r--r-- | Objects/genericaliasobject.c | 39 |
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 * |