| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -72,6 +72,10 @@ PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, | |||
| 72 | 72 | PyObject *item, Py_hash_t hash); | |
| 73 | 73 | #endif | |
| 74 | 74 | PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); | |
| 75 | + #ifndef Py_LIMITED_API | ||
| 76 | + PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, | ||
| 77 | + Py_hash_t hash); | ||
| 78 | + #endif | ||
| 75 | 79 | PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); | |
| 76 | 80 | PyAPI_FUNC(int) PyDict_Next( | |
| 77 | 81 | PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -32,6 +32,9 @@ Core and Builtins | |||
| 32 | 32 | Library | |
| 33 | 33 | ------- | |
| 34 | 34 | ||
| 35 | + - Issue #24483: C implementation of functools.lru_cache() now calculates key's | ||
| 36 | + hash only once. | ||
| 37 | + | ||
| 35 | 38 | - Issue #22958: Constructor and update method of weakref.WeakValueDictionary | |
| 36 | 39 | now accept the self and the dict keyword arguments. | |
| 37 | 40 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -601,6 +601,7 @@ struct lru_cache_object; | |||
| 601 | 601 | typedef struct lru_list_elem { | |
| 602 | 602 | PyObject_HEAD | |
| 603 | 603 | struct lru_list_elem *prev, *next; /* borrowed links */ | |
| 604 | + Py_hash_t hash; | ||
| 604 | 605 | PyObject *key, *result; | |
| 605 | 606 | } lru_list_elem; | |
| 606 | 607 | ||
@@ -762,10 +763,14 @@ static PyObject * | |||
| 762 | 763 | infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) | |
| 763 | 764 | { | |
| 764 | 765 | PyObject *result; | |
| 766 | + Py_hash_t hash; | ||
| 765 | 767 | PyObject *key = lru_cache_make_key(args, kwds, self->typed); | |
| 766 | 768 | if (!key) | |
| 767 | 769 | return NULL; | |
| 768 | - result = PyDict_GetItemWithError(self->cache, key); | ||
| 770 | + hash = PyObject_Hash(key); | ||
| 771 | + if (hash == -1) | ||
| 772 | + return NULL; | ||
| 773 | + result = _PyDict_GetItem_KnownHash(self->cache, key, hash); | ||
| 769 | 774 | if (result) { | |
| 770 | 775 | Py_INCREF(result); | |
| 771 | 776 | self->hits++; | |
@@ -781,7 +786,7 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd | |||
| 781 | 786 | Py_DECREF(key); | |
| 782 | 787 | return NULL; | |
| 783 | 788 | } | |
| 784 | - if (PyDict_SetItem(self->cache, key, result) < 0) { | ||
| 789 | + if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) { | ||
| 785 | 790 | Py_DECREF(result); | |
| 786 | 791 | Py_DECREF(key); | |
| 787 | 792 | return NULL; | |
@@ -813,11 +818,15 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds | |||
| 813 | 818 | { | |
| 814 | 819 | lru_list_elem *link; | |
| 815 | 820 | PyObject *key, *result; | |
| 821 | + Py_hash_t hash; | ||
| 816 | 822 | ||
| 817 | 823 | key = lru_cache_make_key(args, kwds, self->typed); | |
| 818 | 824 | if (!key) | |
| 819 | 825 | return NULL; | |
| 820 | - link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key); | ||
| 826 | + hash = PyObject_Hash(key); | ||
| 827 | + if (hash == -1) | ||
| 828 | + return NULL; | ||
| 829 | + link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash); | ||
| 821 | 830 | if (link) { | |
| 822 | 831 | lru_cache_extricate_link(link); | |
| 823 | 832 | lru_cache_append_link(self, link); | |
@@ -845,7 +854,8 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds | |||
| 845 | 854 | /* Remove it from the cache. | |
| 846 | 855 | The cache dict holds one reference to the link, | |
| 847 | 856 | and the linked list holds yet one reference to it. */ | |
| 848 | - if (PyDict_DelItem(self->cache, link->key) < 0) { | ||
| 857 | + if (_PyDict_DelItem_KnownHash(self->cache, link->key, | ||
| 858 | + link->hash) < 0) { | ||
| 849 | 859 | lru_cache_append_link(self, link); | |
| 850 | 860 | Py_DECREF(key); | |
| 851 | 861 | Py_DECREF(result); | |
@@ -859,9 +869,11 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds | |||
| 859 | 869 | oldkey = link->key; | |
| 860 | 870 | oldresult = link->result; | |
| 861 | 871 | ||
| 872 | + link->hash = hash; | ||
| 862 | 873 | link->key = key; | |
| 863 | 874 | link->result = result; | |
| 864 | - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { | ||
| 875 | + if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, | ||
| 876 | + hash) < 0) { | ||
| 865 | 877 | Py_DECREF(link); | |
| 866 | 878 | Py_DECREF(oldkey); | |
| 867 | 879 | Py_DECREF(oldresult); | |
@@ -881,10 +893,12 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds | |||
| 881 | 893 | return NULL; | |
| 882 | 894 | } | |
| 883 | 895 | ||
| 896 | + link->hash = hash; | ||
| 884 | 897 | link->key = key; | |
| 885 | 898 | link->result = result; | |
| 886 | 899 | _PyObject_GC_TRACK(link); | |
| 887 | - if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) { | ||
| 900 | + if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, | ||
| 901 | + hash) < 0) { | ||
| 888 | 902 | Py_DECREF(link); | |
| 889 | 903 | return NULL; | |
| 890 | 904 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1242,6 +1242,7 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, | |||
| 1242 | 1242 | } | |
| 1243 | 1243 | assert(key); | |
| 1244 | 1244 | assert(value); | |
| 1245 | + assert(hash != -1); | ||
| 1245 | 1246 | mp = (PyDictObject *)op; | |
| 1246 | 1247 | ||
| 1247 | 1248 | /* insertdict() handles any resizing that might be necessary */ | |
@@ -1290,6 +1291,42 @@ PyDict_DelItem(PyObject *op, PyObject *key) | |||
| 1290 | 1291 | return 0; | |
| 1291 | 1292 | } | |
| 1292 | 1293 | ||
| 1294 | + int | ||
| 1295 | + _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) | ||
| 1296 | + { | ||
| 1297 | + PyDictObject *mp; | ||
| 1298 | + PyDictKeyEntry *ep; | ||
| 1299 | + PyObject *old_key, *old_value; | ||
| 1300 | + PyObject **value_addr; | ||
| 1301 | + | ||
| 1302 | + if (!PyDict_Check(op)) { | ||
| 1303 | + PyErr_BadInternalCall(); | ||
| 1304 | + return -1; | ||
| 1305 | + } | ||
| 1306 | + assert(key); | ||
| 1307 | + assert(hash != -1); | ||
| 1308 | + mp = (PyDictObject *)op; | ||
| 1309 | + ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); | ||
| 1310 | + if (ep == NULL) | ||
| 1311 | + return -1; | ||
| 1312 | + if (*value_addr == NULL) { | ||
| 1313 | + _PyErr_SetKeyError(key); | ||
| 1314 | + return -1; | ||
| 1315 | + } | ||
| 1316 | + old_value = *value_addr; | ||
| 1317 | + *value_addr = NULL; | ||
| 1318 | + mp->ma_used--; | ||
| 1319 | + if (!_PyDict_HasSplitTable(mp)) { | ||
| 1320 | + ENSURE_ALLOWS_DELETIONS(mp); | ||
| 1321 | + old_key = ep->me_key; | ||
| 1322 | + Py_INCREF(dummy); | ||
| 1323 | + ep->me_key = dummy; | ||
| 1324 | + Py_DECREF(old_key); | ||
| 1325 | + } | ||
| 1326 | + Py_DECREF(old_value); | ||
| 1327 | + return 0; | ||
| 1328 | + } | ||
| 1329 | + | ||
| 1293 | 1330 | void | |
| 1294 | 1331 | PyDict_Clear(PyObject *op) | |
| 1295 | 1332 | { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments