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 /Objects/genericaliasobject.c | |
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.
Diffstat (limited to 'Objects/genericaliasobject.c')
-rw-r--r-- | Objects/genericaliasobject.c | 39 |
1 files changed, 32 insertions, 7 deletions
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 * |