summaryrefslogtreecommitdiffstats
path: root/Objects/setobject.c
diff options
context:
space:
mode:
authorDong-hee Na <donghee.na92@gmail.com>2020-03-18 17:30:50 (GMT)
committerGitHub <noreply@github.com>2020-03-18 17:30:50 (GMT)
commit1c60567b9a4c8f77e730de9d22690d8e68d7e5f6 (patch)
tree2f9a85cf8399dbbc962da585d430f6f1516d8dcf /Objects/setobject.c
parentd18de46117d661a4acaf2380cc5ebb1cf6a000e9 (diff)
downloadcpython-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.c68
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,
};