diff options
author | Inada Naoki <songofacandy@gmail.com> | 2019-11-08 00:59:04 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-08 00:59:04 +0900 |
commit | 6cbc84fb99acb33dd659d7adb29a20adbe62b74a (patch) | |
tree | 227b48a65e2965719fc86a3c5759f04e6a615c85 /Objects/dictobject.c | |
parent | bpo-38733: PyErr_Occurred() caller must hold the GIL (GH-17080) (diff) | |
download | cpython-6cbc84fb99acb33dd659d7adb29a20adbe62b74a.tar.gz cpython-6cbc84fb99acb33dd659d7adb29a20adbe62b74a.tar.bz2 cpython-6cbc84fb99acb33dd659d7adb29a20adbe62b74a.zip |
bpo-38613: Optimize set operations of dict keys. (GH-16961)
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r-- | Objects/dictobject.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d909f220a98..4afa19c8a0a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4162,17 +4162,34 @@ static PySequenceMethods dictkeys_as_sequence = { (objobjproc)dictkeys_contains, /* sq_contains */ }; +// Create an set object from dictviews object. +// Returns a new reference. +// This utility function is used by set operations. static PyObject* -dictviews_sub(PyObject* self, PyObject *other) +dictviews_to_set(PyObject *self) { - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(difference_update); + PyObject *left = self; + if (PyDictKeys_Check(self)) { + // PySet_New() has fast path for the dict object. + PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict; + if (PyDict_CheckExact(dict)) { + left = dict; + } + } + return PySet_New(left); +} - if (result == NULL) +static PyObject* +dictviews_sub(PyObject *self, PyObject *other) +{ + PyObject *result = dictviews_to_set(self); + if (result == NULL) { return NULL; + } - tmp = _PyObject_CallMethodIdOneArg(result, &PyId_difference_update, other); + _Py_IDENTIFIER(difference_update); + PyObject *tmp = _PyObject_CallMethodIdOneArg( + result, &PyId_difference_update, other); if (tmp == NULL) { Py_DECREF(result); return NULL; @@ -4273,34 +4290,29 @@ error: static PyObject* dictviews_or(PyObject* self, PyObject *other) { - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(update); - - if (result == NULL) + PyObject *result = dictviews_to_set(self); + if (result == NULL) { return NULL; + } - tmp = _PyObject_CallMethodIdOneArg(result, &PyId_update, other); - if (tmp == NULL) { + if (_PySet_Update(result, other) < 0) { Py_DECREF(result); return NULL; } - - Py_DECREF(tmp); return result; } static PyObject* dictviews_xor(PyObject* self, PyObject *other) { - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(symmetric_difference_update); - - if (result == NULL) + PyObject *result = dictviews_to_set(self); + if (result == NULL) { return NULL; + } - tmp = _PyObject_CallMethodIdOneArg(result, &PyId_symmetric_difference_update, other); + _Py_IDENTIFIER(symmetric_difference_update); + PyObject *tmp = _PyObject_CallMethodIdOneArg( + result, &PyId_symmetric_difference_update, other); if (tmp == NULL) { Py_DECREF(result); return NULL; |