8000 bpo-37207: Use PEP 590 vectorcall to speed up frozenset() (GH-19053) · python/cpython@1c60567 · GitHub
[go: up one dir, main page]

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1c60567

Browse files
authored
bpo-37207: Use PEP 590 vectorcall to speed up frozenset() (GH-19053)
1 parent d18de46 commit 1c60567

File tree

2 files changed

+52
-18
lines changed

2 files changed

+52
-18
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up calls to ``frozenset()`` by using the :pep:`590` ``vectorcall``
2+
calling convention. Pat 8000 ch by Dong-hee Na.

Objects/setobject.c

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,7 @@ PyDoc_STRVAR(update_doc,
10241024
static PyObject *
10251025
make_new_set(PyTypeObject *type, PyObject *iterable)
10261026
{
1027+
assert(PyType_Check(type));
10271028
PySetObject *so;
10281029

10291030
so = (PySetObject *)type->tp_alloc(type, 0);
@@ -1064,37 +1065,67 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
10641065
static PyObject *emptyfrozenset = NULL;
10651066

10661067
static PyObject *
1067-
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1068+
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
10681069
{
1069-
PyObject *iterable = NULL, *result;
1070-
1071-
if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset", kwds))
1072-
return NULL;
1073-
1074-
if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
1075-
return NULL;
1076-
1077-
if (type != &PyFrozenSet_Type)
1070+
if (type != &PyFrozenSet_Type) {
10781071
return make_new_set(type, iterable);
1072+
}
10791073

10801074
if (iterable != NULL) {
1081-
/* frozenset(f) is idempotent */
10821075
if (PyFrozenSet_CheckExact(iterable)) {
1076+
/* frozenset(f) is idempotent */
10831077
Py_INCREF(iterable);
10841078
return iterable;
10851079
}
1086-
result = make_new_set(type, iterable);
1087-
if (result == NULL || PySet_GET_SIZE(result))
1088-
return result;
1089-
Py_DECREF(result);
1080+
PyObject *res = make_new_set((PyTypeObject *)type, iterable);
1081+
if (res == NULL || PySet_GET_SIZE(res) != 0) {
1082+
return res;
1083+
}
1084+
/* If the created frozenset is empty, return the empty frozenset singleton instead */
1085+
Py_DECREF(res);
1086+
}
1087+
1088+
// The empty frozenset is a singleton
1089+
if (emptyfrozenset == NULL) {
1090+
emptyfrozenset = make_new_set((PyTypeObject *)type, NULL);
10901091
}
1091-
/* The empty frozenset is a singleton */
1092-
if (emptyfrozenset == NULL)
1093-
emptyfrozenset = make_new_set(type, NULL);
10941092
Py_XINCREF(emptyfrozenset);
10951093
return emptyfrozenset;
10961094
}
10971095

1096+
static PyObject *
1097+
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1098+
{
1099+
PyObject *iterable = NULL;
1100+
1101+
if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset", kwds)) {
1102+
return NULL;
1103+
}
1104+
1105+
if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1106+
return NULL;
1107+
}
1108+
1109+
return make_new_frozenset(type, iterable);
1110+
}
1111+
1112+
static PyObject *
1113+
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1114+
size_t nargsf, PyObject *kwnames)
1115+
{
1116+
if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1117+
return NULL;
1118+
}
1119+
1120+
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1121+
if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1122+
return NULL;
1123+
}
1124+
1125+
PyObject *iterable = (nargs ? args[0] : NULL);
1126+
return make_new_frozenset((PyTypeObject *)type, iterable);
1127+
}
1128+
10981129
static PyObject *
10991130
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11001131
{
@@ -2283,6 +2314,7 @@ PyTypeObject PyFrozenSet_Type = {
22832314
PyType_GenericAlloc, /* tp_alloc */
22842315
frozenset_new, /* tp_new */
22852316
PyObject_GC_Del, /* tp_free */
2317+
.tp_vectorcall = frozenset_vectorcall,
22862318
};
22872319

22882320

0 commit comments

Comments
 (0)
0