summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorDonghee Na <donghee.na@python.org>2024-03-15 14:48:34 (GMT)
committerGitHub <noreply@github.com>2024-03-15 14:48:34 (GMT)
commit8da83f3386da603605358dc9ec68796daa5ef455 (patch)
treec3e5d48a4a6579a1233efbea789028ed7c94dc9b /Objects
parent59e30f41ed6f2388a99ac0a8aebf0a12f7460a4a (diff)
downloadcpython-8da83f3386da603605358dc9ec68796daa5ef455.zip
cpython-8da83f3386da603605358dc9ec68796daa5ef455.tar.gz
cpython-8da83f3386da603605358dc9ec68796daa5ef455.tar.bz2
gh-116621: Specialize list.extend for dict keys/values (gh-116816)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/listobject.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 7179d59..6f919ce 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -3,6 +3,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
+#include "pycore_dict.h" // _PyDictViewObject
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_interp.h" // PyInterpreterState.list
#include "pycore_list.h" // struct _Py_list_freelist, _PyListIterObject
@@ -1296,6 +1297,30 @@ list_extend_set(PyListObject *self, PySetObject *other)
}
static int
+list_extend_dict(PyListObject *self, PyDictObject *dict, int which_item)
+{
+ // which_item: 0 for keys and 1 for values
+ Py_ssize_t m = Py_SIZE(self);
+ Py_ssize_t n = PyDict_GET_SIZE(dict);
+ if (list_resize(self, m + n) < 0) {
+ return -1;
+ }
+
+ PyObject **dest = self->ob_item + m;
+ Py_ssize_t pos = 0;
+ PyObject *keyvalue[2];
+ while (_PyDict_Next((PyObject *)dict, &pos, &keyvalue[0], &keyvalue[1], NULL)) {
+ PyObject *obj = keyvalue[which_item];
+ Py_INCREF(obj);
+ *dest = obj;
+ dest++;
+ }
+
+ Py_SET_SIZE(self, m + n);
+ return 0;
+}
+
+static int
_list_extend(PyListObject *self, PyObject *iterable)
{
// Special case:
@@ -1322,6 +1347,18 @@ _list_extend(PyListObject *self, PyObject *iterable)
res = list_extend_set(self, (PySetObject *)iterable);
Py_END_CRITICAL_SECTION2();
}
+ else if (Py_IS_TYPE(iterable, &PyDictKeys_Type)) {
+ PyDictObject *dict = ((_PyDictViewObject *)iterable)->dv_dict;
+ Py_BEGIN_CRITICAL_SECTION2(self, dict);
+ res = list_extend_dict(self, dict, 0 /*keys*/);
+ Py_END_CRITICAL_SECTION2();
+ }
+ else if (Py_IS_TYPE(iterable, &PyDictValues_Type)) {
+ PyDictObject *dict = ((_PyDictViewObject *)iterable)->dv_dict;
+ Py_BEGIN_CRITICAL_SECTION2(self, dict);
+ res = list_extend_dict(self, dict, 1 /*values*/);
+ Py_END_CRITICAL_SECTION2();
+ }
else {
Py_BEGIN_CRITICAL_SECTION(self);
res = list_extend_iter_lock_held(self, iterable);