diff options
author | Dong-hee Na <donghee.na92@gmail.com> | 2020-03-18 17:30:50 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-18 17:30:50 (GMT) |
commit | 1c60567b9a4c8f77e730de9d22690d8e68d7e5f6 (patch) | |
tree | 2f9a85cf8399dbbc962da585d430f6f1516d8dcf /Objects/setobject.c | |
parent | d18de46117d661a4acaf2380cc5ebb1cf6a000e9 (diff) | |
download | cpython-1c60567b9a4c8f77e730de9d22690d8e68d7e5f6.zip cpython-1c60567b9a4c8f77e730de9d22690d8e68d7e5f6.tar.gz cpython-1c60567b9a4c8f77e730de9d22690d8e68d7e5f6.tar.bz2 |
bpo-37207: Use PEP 590 vectorcall to speed up frozenset() (GH-19053)
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r-- | Objects/setobject.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index 9f424b3..41b9ecd 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1024,6 +1024,7 @@ PyDoc_STRVAR(update_doc, static PyObject * make_new_set(PyTypeObject *type, PyObject *iterable) { + assert(PyType_Check(type)); PySetObject *so; so = (PySetObject *)type->tp_alloc(type, 0); @@ -1064,38 +1065,68 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable) static PyObject *emptyfrozenset = NULL; static PyObject * -frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +make_new_frozenset(PyTypeObject *type, PyObject *iterable) { - PyObject *iterable = NULL, *result; - - if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset", kwds)) - return NULL; - - if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) - return NULL; - - if (type != &PyFrozenSet_Type) + if (type != &PyFrozenSet_Type) { return make_new_set(type, iterable); + } if (iterable != NULL) { - /* frozenset(f) is idempotent */ if (PyFrozenSet_CheckExact(iterable)) { + /* frozenset(f) is idempotent */ Py_INCREF(iterable); return iterable; } - result = make_new_set(type, iterable); - if (result == NULL || PySet_GET_SIZE(result)) - return result; - Py_DECREF(result); + PyObject *res = make_new_set((PyTypeObject *)type, iterable); + if (res == NULL || PySet_GET_SIZE(res) != 0) { + return res; + } + /* If the created frozenset is empty, return the empty frozenset singleton instead */ + Py_DECREF(res); + } + + // The empty frozenset is a singleton + if (emptyfrozenset == NULL) { + emptyfrozenset = make_new_set((PyTypeObject *)type, NULL); } - /* The empty frozenset is a singleton */ - if (emptyfrozenset == NULL) - emptyfrozenset = make_new_set(type, NULL); Py_XINCREF(emptyfrozenset); return emptyfrozenset; } static PyObject * +frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *iterable = NULL; + + if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset", kwds)) { + return NULL; + } + + if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) { + return NULL; + } + + return make_new_frozenset(type, iterable); +} + +static PyObject * +frozenset_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) +{ + if (!_PyArg_NoKwnames("frozenset", kwnames)) { + return NULL; + } + + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) { + return NULL; + } + + PyObject *iterable = (nargs ? args[0] : NULL); + return make_new_frozenset((PyTypeObject *)type, iterable); +} + +static PyObject * set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { return make_new_set(type, NULL); @@ -2283,6 +2314,7 @@ PyTypeObject PyFrozenSet_Type = { PyType_GenericAlloc, /* tp_alloc */ frozenset_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ + .tp_vectorcall = frozenset_vectorcall, }; |