8000 gh-116621: Specialize list.extend for dict keys/values (gh-116816) · python/cpython@8da83f3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8da83f3

Browse files
authored
gh-116621: Specialize list.extend for dict keys/values (gh-116816)
1 parent 59e30f4 commit 8da83f3

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

Objects/listobject.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Python.h"
44
#include "pycore_abstract.h" // _PyIndex_Check()
55
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
6+
#include "pycore_dict.h" // _PyDictViewObject
67
#include "pycore_pyatomic_ft_wrappers.h"
78
#include "pycore_interp.h" // PyInterpreterState.list
89
#include "pycore_list.h" // struct _Py_list_freelist, _PyListIterObject
@@ -1295,6 +1296,30 @@ list_extend_set(PyListObject *self, PySetObject *other)
12951296
return 0;
12961297
}
12971298

1299+
static int
1300+
list_extend_dict(PyListObject *self, PyDictObject *dict, int which_item)
1301+
{
1302+
// which_item: 0 for keys and 1 for values
1303+
Py_ssize_t m = Py_SIZE(self);
1304+
Py_ssize_t n = PyDict_GET_SIZE(dict);
1305+
if (list_resize(self, m + n) < 0) {
1306+
return -1;
1307+
}
1308+
1309+
PyObject **dest = self->ob_item + m;
1310+
Py_ssize_t pos = 0;
1311+
PyObject *keyvalue[2];
1312+
while (_PyDict_Next((PyObject *)dict, &pos, &keyvalue[0], &keyvalue[1], NULL)) {
1313+
PyObject *obj = keyvalue[which_item];
1314+
Py_INCREF(obj);
1315+
*dest = obj;
1316+
dest++;
1317+
}
1318+
1319+
Py_SET_SIZE(self, m + n);
1320+
return 0;
1321+
}
1322+
12981323
static int
12991324
_list_extend(PyListObject *self, PyObject *iterable)
13001325
{
@@ -1322,6 +1347,18 @@ _list_extend(PyListObject *self, PyObject *iterable)
13221347
res = list_extend_set(self, (PySetObject *)iterable);
13231348
Py_END_CRITICAL_SECTION2();
13241349
}
1350+
else if (Py_IS_TYPE(iterable, &PyDictKeys_Type)) {
1351+
PyDictObject *dict = ((_PyDictViewObject *)iterable)->dv_dict;
1352+
Py_BEGIN_CRITICAL_SECTION2(self, dict);
1353+
res = list_extend_dict(self, dict, 0 /*keys*/);
1354+
Py_END_CRITICAL_SECTION2();
1355+
}
1356+
else if (Py_IS_TYPE(iterable, &PyDictValues_Type)) {
1357+
PyDictObject *dict = ((_PyDictViewObject *)iterable)->dv_dict;
1358+
Py_BEGIN_CRITICAL_SECTION2(self, dict);
1359+
res = list_extend_dict(self, dict, 1 /*values*/);
1360+
Py_END_CRITICAL_SECTION2();
1361+
}
13251362
else {
13261363
Py_BEGIN_CRITICAL_SECTION(self);
13271364
res = list_extend_iter_lock_held(self, iterable);

0 commit comments

Comments
 (0)
0