10#include "nuitka/prelude.h"
22#define PyDict_LOG_MINSIZE 3
24#if defined(WITH_FREELISTS) && PYTHON_VERSION >= 0x3d0
25static struct _Py_dictkeys_freelist *get_dictkeys_freelist(
void) {
26 struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
27 return &freelists->dictkeys;
31static void Nuitka_Py_dictkeys_free_keys_object(PyDictKeysObject *keys,
bool use_qsbr) {
34 _PyMem_FreeDelayed(keys);
39#if defined(WITH_FREELISTS) && PYTHON_VERSION >= 0x3d0
40 struct _Py_dictkeys_freelist *freelist = get_dictkeys_freelist();
41 if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE && freelist->numfree < PyDict_MAXFREELIST && freelist->numfree >= 0 &&
42 DK_IS_UNICODE(keys)) {
43 freelist->items[freelist->numfree++] = keys;
54static inline void ASSERT_DICT_LOCKED(PyObject *op) { _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op); }
55#define ASSERT_DICT_LOCKED(op) ASSERT_DICT_LOCKED(_Py_CAST(PyObject *, op))
56#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op) \
57 if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) { \
58 ASSERT_DICT_LOCKED(op); \
60#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op) \
61 if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) { \
62 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op); \
65#define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
66#define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
67#define LOAD_INDEX(keys, size, idx) \
68 _Py_atomic_load_int##size##_relaxed(&((const int##size##_t *)keys->dk_indices)[idx]);
69#define STORE_INDEX(keys, size, idx, value) \
70 _Py_atomic_store_int##size##_relaxed(&((int##size##_t *)keys->dk_indices)[idx], (int##size##_t)value);
71#define ASSERT_OWNED_OR_SHARED(mp) assert(_Py_IsOwnedByCurrentThread((PyObject *)mp) || IS_DICT_SHARED(mp));
73#define LOCK_KEYS_IF_SPLIT(keys, kind) \
74 if (kind == DICT_KEYS_SPLIT) { \
78#define UNLOCK_KEYS_IF_SPLIT(keys, kind) \
79 if (kind == DICT_KEYS_SPLIT) { \
83#define LOCK_KEYS(keys) PyMutex_LockFlags(&keys->dk_mutex, _Py_LOCK_DONT_DETACH)
84#define UNLOCK_KEYS(keys) PyMutex_Unlock(&keys->dk_mutex)
86#define ASSERT_KEYS_LOCKED(keys) assert(PyMutex_IsLocked(&keys->dk_mutex))
87#define LOAD_SHARED_KEY(key) _Py_atomic_load_ptr_acquire(&key)
88#define STORE_SHARED_KEY(key, value) _Py_atomic_store_ptr_release(&key, value)
90#define INCREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, 1)
92#define DECREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, -1)
93#define LOAD_KEYS_NENTRIES(keys) _Py_atomic_load_ssize_relaxed(&keys->dk_nentries)
95static inline void Nuitka_Py_dictkeys_incref(PyDictKeysObject *dk) {
96 if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) {
100 _Py_IncRefTotal(_PyThreadState_GET());
105static inline void Nuitka_Py_dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk,
bool use_qsbr) {
106 if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) {
109 assert(FT_ATOMIC_LOAD_SSIZE(dk->dk_refcnt) > 0);
111 _Py_DecRefTotal(_PyThreadState_GET());
113 if (DECREF_KEYS(dk) == 1) {
114 if (DK_IS_UNICODE(dk)) {
115 PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dk);
117 for (i = 0, n = dk->dk_nentries; i < n; i++) {
118 Py_XDECREF(entries[i].me_key);
119 Py_XDECREF(entries[i].me_value);
122 PyDictKeyEntry *entries = DK_ENTRIES(dk);
124 for (i = 0, n = dk->dk_nentries; i < n; i++) {
125 Py_XDECREF(entries[i].me_key);
126 Py_XDECREF(entries[i].me_value);
129 Nuitka_Py_dictkeys_free_keys_object(dk, use_qsbr);
133#define INCREF_KEYS_FT(dk) Nuitka_Py_dictkeys_incref(dk)
134#define DECREF_KEYS_FT(dk, shared) Nuitka_Py_dictkeys_decref(_PyInterpreterState_GET(), dk, shared)
136static inline void split_keys_entry_added(PyDictKeysObject *keys) {
137 ASSERT_KEYS_LOCKED(keys);
141 _Py_atomic_store_ssize_relaxed(&keys->dk_nentries, keys->dk_nentries + 1);
142 _Py_atomic_store_ssize_release(&keys->dk_usable, keys->dk_usable - 1);
147#define ASSERT_DICT_LOCKED(op)
148#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
149#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
150#define LOCK_KEYS(keys)
151#define UNLOCK_KEYS(keys)
152#define ASSERT_KEYS_LOCKED(keys)
153#define LOAD_SHARED_KEY(key) key
154#define STORE_SHARED_KEY(key, value) key = value
155#define INCREF_KEYS(dk) dk->dk_refcnt++
156#define DECREF_KEYS(dk) dk->dk_refcnt--
157#define LOAD_KEYS_NENTRIES(keys) keys->dk_nentries
158#define INCREF_KEYS_FT(dk)
159#define DECREF_KEYS_FT(dk, shared)
160#define LOCK_KEYS_IF_SPLIT(keys, kind)
161#define UNLOCK_KEYS_IF_SPLIT(keys, kind)
162#define IS_DICT_SHARED(mp) (false)
163#define SET_DICT_SHARED(mp)
164#define LOAD_INDEX(keys, size, idx) ((const int##size##_t *)(keys->dk_indices))[idx]
165#define STORE_INDEX(keys, size, idx, value) ((int##size##_t *)(keys->dk_indices))[idx] = (int##size##_t)value
168Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
170PyObject *DICT_GET_ITEM0(PyThreadState *tstate, PyObject *dict, PyObject *key) {
172 assert(PyDict_Check(dict));
179#if PYTHON_VERSION < 0x300
180 if (PyString_CheckExact(key)) {
181 hash = ((PyStringObject *)key)->ob_shash;
183 if (unlikely(hash == -1)) {
184 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
187 if (unlikely(hash == -1)) {
191 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
193 if (unlikely(hash == -1)) {
198 PyDictObject *dict_object = (PyDictObject *)dict;
199 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
201 if (unlikely(entry == NULL || entry->me_value == NULL)) {
205 CHECK_OBJECT(entry->me_value);
206 return entry->me_value;
208 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
209 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
211 if (unlikely(hash == -1)) {
216 PyDictObject *dict_object = (PyDictObject *)dict;
218#if PYTHON_VERSION < 0x360
219 PyObject **value_addr;
220 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
222 if (unlikely(entry == NULL || *value_addr == NULL)) {
226#if PYTHON_VERSION < 0x370
227 PyObject **value_addr;
228 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
229#elif PYTHON_VERSION < 0x3b0
231 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
232#elif defined(Py_GIL_DISABLED)
234 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
236 PyObject **value_addr;
237 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
240 if (unlikely(ix < 0)) {
245#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
246 assert(value_addr != NULL);
247 PyObject *result = *value_addr;
249 if (unlikely(result == NULL)) {
253 CHECK_OBJECT(result);
258PyObject *DICT_GET_ITEM1(PyThreadState *tstate, PyObject *dict, PyObject *key) {
260 assert(PyDict_Check(dict));
267#if PYTHON_VERSION < 0x300
268 if (PyString_CheckExact(key)) {
269 hash = ((PyStringObject *)key)->ob_shash;
271 if (unlikely(hash == -1)) {
272 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
275 if (unlikely(hash == -1)) {
279 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
281 if (unlikely(hash == -1)) {
286 PyDictObject *dict_object = (PyDictObject *)dict;
287 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
289 if (unlikely(entry == NULL || entry->me_value == NULL)) {
293 CHECK_OBJECT(entry->me_value);
294 Py_INCREF(entry->me_value);
295 return entry->me_value;
297 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
298 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
300 if (unlikely(hash == -1)) {
305 PyDictObject *dict_object = (PyDictObject *)dict;
307#if PYTHON_VERSION < 0x360
308 PyObject **value_addr;
309 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
311 if (unlikely(entry == NULL || *value_addr == NULL)) {
315#if PYTHON_VERSION < 0x370
316 PyObject **value_addr;
317 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
318#elif PYTHON_VERSION < 0x3b0
320 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
321#elif defined(Py_GIL_DISABLED)
323 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
325 PyObject **value_addr;
326 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
329 if (unlikely(ix < 0)) {
334#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
335 assert(value_addr != NULL);
336 PyObject *result = *value_addr;
338 if (unlikely(result == NULL)) {
342 CHECK_OBJECT(result);
348#if PYTHON_VERSION >= 0x3c0
349static PyObject *Nuitka_CreateKeyError(PyThreadState *tstate, PyObject *key) {
350 return (PyObject *)Nuitka_BaseExceptionSingleArg_new(tstate, (PyTypeObject *)PyExc_KeyError, key);
354static void SET_CURRENT_EXCEPTION_KEY_ERROR(PyThreadState *tstate, PyObject *key) {
355#if PYTHON_VERSION < 0x3c0
360 if (PyTuple_Check(key) || key == Py_None) {
361 PyObject *tuple = MAKE_TUPLE1(tstate, key);
363 SET_CURRENT_EXCEPTION_TYPE0_VALUE1(tstate, PyExc_KeyError, tuple);
365 SET_CURRENT_EXCEPTION_TYPE0_VALUE0(tstate, PyExc_KeyError, key);
370 RESTORE_ERROR_OCCURRED_STATE(tstate, &exception_state);
381PyObject *DICT_GET_ITEM_WITH_ERROR(PyThreadState *tstate, PyObject *dict, PyObject *key) {
383 assert(PyDict_CheckExact(dict));
390#if PYTHON_VERSION < 0x300
391 if (PyString_CheckExact(key)) {
392 hash = ((PyStringObject *)key)->ob_shash;
394 if (unlikely(hash == -1)) {
395 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
398 if (unlikely(hash == -1)) {
402 hash = HASH_VALUE_WITH_ERROR(tstate, key);
404 if (unlikely(hash == -1)) {
409 PyDictObject *dict_object = (PyDictObject *)dict;
410 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
412 if (unlikely(entry == NULL || entry->me_value == NULL)) {
413 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
418 CHECK_OBJECT(entry->me_value);
419 Py_INCREF(entry->me_value);
420 return entry->me_value;
422 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
423 hash = HASH_VALUE_WITH_ERROR(tstate, key);
424 if (unlikely(hash == -1)) {
429 PyDictObject *dict_object = (PyDictObject *)dict;
431#if PYTHON_VERSION < 0x360
432 PyObject **value_addr;
433 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
435 if (unlikely(entry == NULL || *value_addr == NULL)) {
436 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
440 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
445#if PYTHON_VERSION < 0x370
446 PyObject **value_addr;
447 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
448#elif PYTHON_VERSION < 0x3b0
450 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
451#elif defined(Py_GIL_DISABLED)
453 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
455 PyObject **value_addr;
456 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
459 if (unlikely(ix < 0)) {
460 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
464 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
470#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
471 assert(value_addr != NULL);
472 PyObject *result = *value_addr;
475 if (unlikely(result == NULL)) {
476 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
480 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
485 CHECK_OBJECT(result);
491PyObject *DICT_GET_ITEM_WITH_HASH_ERROR0(PyThreadState *tstate, PyObject *dict, PyObject *key) {
493 assert(PyDict_CheckExact(dict));
500#if PYTHON_VERSION < 0x300
501 if (PyString_CheckExact(key)) {
502 hash = ((PyStringObject *)key)->ob_shash;
504 if (unlikely(hash == -1)) {
505 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
508 if (unlikely(hash == -1)) {
512 hash = HASH_VALUE_WITH_ERROR(tstate, key);
514 if (unlikely(hash == -1)) {
519 PyDictObject *dict_object = (PyDictObject *)dict;
520 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
522 if (unlikely(entry == NULL || entry->me_value == NULL)) {
526 CHECK_OBJECT(entry->me_value);
527 return entry->me_value;
529 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
530 hash = HASH_VALUE_WITH_ERROR(tstate, key);
531 if (unlikely(hash == -1)) {
536 PyDictObject *dict_object = (PyDictObject *)dict;
538#if PYTHON_VERSION < 0x360
539 PyObject **value_addr;
540 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
542 if (unlikely(entry == NULL || *value_addr == NULL)) {
546#if PYTHON_VERSION < 0x370
547 PyObject **value_addr;
548 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
549#elif PYTHON_VERSION < 0x3b0
551 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
552#elif defined(Py_GIL_DISABLED)
554 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
556 PyObject **value_addr;
557 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
560 if (unlikely(ix < 0)) {
565#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
566 assert(value_addr != NULL);
567 PyObject *result = *value_addr;
570 if (unlikely(result == NULL)) {
574 CHECK_OBJECT(result);
582PyObject *DICT_GET_ITEM_WITH_HASH_ERROR1(PyThreadState *tstate, PyObject *dict, PyObject *key) {
584 assert(PyDict_CheckExact(dict));
591#if PYTHON_VERSION < 0x300
592 if (PyString_CheckExact(key)) {
593 hash = ((PyStringObject *)key)->ob_shash;
595 if (unlikely(hash == -1)) {
596 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
599 if (unlikely(hash == -1)) {
603 hash = HASH_VALUE_WITH_ERROR(tstate, key);
605 if (unlikely(hash == -1)) {
610 PyDictObject *dict_object = (PyDictObject *)dict;
611 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
613 if (unlikely(entry == NULL || entry->me_value == NULL)) {
617 CHECK_OBJECT(entry->me_value);
618 Py_INCREF(entry->me_value);
619 return entry->me_value;
621 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
622 hash = HASH_VALUE_WITH_ERROR(tstate, key);
623 if (unlikely(hash == -1)) {
628 PyDictObject *dict_object = (PyDictObject *)dict;
630#if PYTHON_VERSION < 0x360
631 PyObject **value_addr;
632 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
634 if (unlikely(entry == NULL || *value_addr == NULL)) {
638#if PYTHON_VERSION < 0x370
639 PyObject **value_addr;
640 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
641#elif PYTHON_VERSION < 0x3b0
643 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
644#elif defined(Py_GIL_DISABLED)
646 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
648 PyObject **value_addr;
649 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
652 if (unlikely(ix < 0)) {
657#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
658 assert(value_addr != NULL);
659 PyObject *result = *value_addr;
662 if (unlikely(result == NULL)) {
666 CHECK_OBJECT(result);
672int DICT_HAS_ITEM(PyThreadState *tstate, PyObject *dict, PyObject *key) {
674 assert(PyDict_Check(dict));
681#if PYTHON_VERSION < 0x300
682 if (PyString_CheckExact(key)) {
683 hash = ((PyStringObject *)key)->ob_shash;
685 if (unlikely(hash == -1)) {
686 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
689 if (unlikely(hash == -1)) {
693 hash = HASH_VALUE_WITH_ERROR(tstate, key);
695 if (unlikely(hash == -1)) {
700 PyDictObject *dict_object = (PyDictObject *)dict;
701 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
703 if (unlikely(entry == NULL || entry->me_value == NULL)) {
709 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
710 hash = HASH_VALUE_WITH_ERROR(tstate, key);
711 if (unlikely(hash == -1)) {
716 PyDictObject *dict_object = (PyDictObject *)dict;
718#if PYTHON_VERSION < 0x360
719 PyObject **value_addr;
720 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
722 if (unlikely(entry == NULL || *value_addr == NULL)) {
728#if PYTHON_VERSION < 0x370
729 PyObject **value_addr;
730 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
731#elif PYTHON_VERSION < 0x3b0
733 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
734#elif defined(Py_GIL_DISABLED)
736 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
738 PyObject **value_addr;
739 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
742 if (unlikely(ix < 0)) {
743 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
750#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
751 assert(value_addr != NULL);
752 PyObject *result = *value_addr;
755 if (unlikely(result == NULL)) {
763#if PYTHON_VERSION < 0x300
764PyObject *DICT_ITEMS(PyObject *dict) {
766 assert(PyDict_Check(dict));
768 PyDictObject *mp = (PyDictObject *)dict;
779 result = MAKE_LIST_EMPTY(tstate, size);
780 CHECK_OBJECT(result);
782 for (Py_ssize_t i = 0; i < size; i++) {
784 PyObject *item = MAKE_TUPLE_EMPTY(tstate, 2);
787 PyList_SET_ITEM(result, i, item);
790 if (unlikely(size != mp->ma_used)) {
797 PyDictEntry *ep = mp->ma_table;
798 Py_ssize_t mask = mp->ma_mask;
800 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
801 PyObject *value = ep[i].me_value;
803 PyObject *key = ep[i].me_key;
804 PyObject *item = PyList_GET_ITEM(result, j);
805 PyTuple_SET_ITEM0(item, 0, key);
806 PyTuple_SET_ITEM0(item, 1, value);
812 assert(PyList_GET_SIZE(result) == size);
817#if PYTHON_VERSION < 0x300
818PyObject *DICT_KEYS(PyObject *dict) {
820 assert(PyDict_Check(dict));
822 PyDictObject *mp = (PyDictObject *)dict;
833 result = MAKE_LIST_EMPTY(tstate, size);
834 CHECK_OBJECT(result);
836 if (unlikely(size != mp->ma_used)) {
843 PyDictEntry *ep = mp->ma_table;
844 Py_ssize_t mask = mp->ma_mask;
846 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
847 PyObject *value = ep[i].me_value;
849 PyObject *key = ep[i].me_key;
850 PyList_SET_ITEM0(result, j, key);
856 assert(PyList_GET_SIZE(result) == size);
862#if PYTHON_VERSION < 0x300
863PyObject *DICT_VALUES(PyObject *dict) {
865 assert(PyDict_Check(dict));
867 PyDictObject *mp = (PyDictObject *)dict;
878 result = MAKE_LIST_EMPTY(tstate, size);
879 CHECK_OBJECT(result);
881 if (unlikely(size != mp->ma_used)) {
888 PyDictEntry *ep = mp->ma_table;
889 Py_ssize_t mask = mp->ma_mask;
891 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
892 PyObject *value = ep[i].me_value;
894 PyList_SET_ITEM0(result, j, value);
900 assert(PyList_GET_SIZE(result) == size);
908#if PYTHON_VERSION < 0x300
910 PyObject_HEAD PyDictObject *di_dict;
918#if PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x350
920 PyObject_HEAD PyDictObject *dv_dict;
926static inline PyObject *_MAKE_DICT_ITERATOR(PyThreadState *tstate, PyDictObject *dict, PyTypeObject *type,
928 CHECK_OBJECT((PyObject *)dict);
929 assert(PyDict_CheckExact((PyObject *)dict));
931#if PYTHON_VERSION < 0x300
936 di->di_used = dict->ma_used;
938 di->len = dict->ma_used;
941 di->di_result = MAKE_TUPLE2(tstate, Py_None, Py_None);
942 CHECK_OBJECT(di->di_result);
944 di->di_result = NULL;
948 return (PyObject *)di;
950 _PyDictViewObject *dv = (_PyDictViewObject *)Nuitka_GC_New(type);
957 return (PyObject *)dv;
961PyObject *DICT_ITERITEMS(PyThreadState *tstate, PyObject *dict) {
962#if PYTHON_VERSION < 0x270
963 static PyTypeObject *dictiteritems_type = NULL;
965 if (unlikely(dictiteritems_type == NULL)) {
967 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"iteritems")));
970 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictiteritems_type,
true);
971#elif PYTHON_VERSION < 0x300
972 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterItem_Type,
true);
974 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictItems_Type,
true);
978PyObject *DICT_ITERKEYS(PyThreadState *tstate, PyObject *dict) {
979#if PYTHON_VERSION < 0x270
980 static PyTypeObject *dictiterkeys_type = NULL;
982 if (unlikely(dictiterkeys_type == NULL)) {
984 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"iterkeys")));
987 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictiterkeys_type,
false);
988#elif PYTHON_VERSION < 0x300
989 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterKey_Type,
false);
991 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictKeys_Type,
false);
995PyObject *DICT_ITERVALUES(PyThreadState *tstate, PyObject *dict) {
996#if PYTHON_VERSION < 0x270
997 static PyTypeObject *dictitervalues_type = NULL;
999 if (unlikely(dictitervalues_type == NULL)) {
1000 dictitervalues_type =
1001 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"itervalues")));
1004 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictitervalues_type,
false);
1005#elif PYTHON_VERSION < 0x300
1006 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterValue_Type,
false);
1008 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictValues_Type,
false);
1013 PyObject_HEAD PyDictObject *dv_dict;
1016static PyObject *_MAKE_DICT_VIEW(PyDictObject *dict, PyTypeObject *type) {
1017 CHECK_OBJECT((PyObject *)dict);
1018 assert(PyDict_CheckExact((PyObject *)dict));
1024 dv->dv_dict = (PyDictObject *)dict;
1025 Nuitka_GC_Track(dv);
1026 return (PyObject *)dv;
1029PyObject *DICT_VIEWKEYS(PyObject *dict) {
1030#if PYTHON_VERSION < 0x270
1031 static PyTypeObject *dictkeysview_type = NULL;
1033 if (unlikely(dictkeysview_type)) {
1034 dictkeysview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewkeys")));
1037 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictkeysview_type);
1039 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictKeys_Type);
1043PyObject *DICT_VIEWVALUES(PyObject *dict) {
1044#if PYTHON_VERSION < 0x270
1045 static PyTypeObject *dictvaluesview_type = NULL;
1047 if (unlikely(dictvaluesview_type)) {
1048 dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewvalues")));
1051 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type);
1053 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictValues_Type);
1057PyObject *DICT_VIEWITEMS(PyObject *dict) {
1058#if PYTHON_VERSION < 0x270
1059 static PyTypeObject *dictvaluesview_type = NULL;
1061 if (unlikely(dictvaluesview_type)) {
1062 dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewitems")));
1065 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type);
1067 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictItems_Type);
1071#if PYTHON_VERSION >= 0x300
1072static PyDictObject *_Nuitka_AllocatePyDictObject(PyThreadState *tstate) {
1073 PyDictObject *result_mp;
1075#if NUITKA_DICT_HAS_FREELIST
1076#if PYTHON_VERSION >= 0x3e0
1078 result_mp = (PyDictObject *)Nuitka_PyFreeList_Pop(&_Py_freelists_GET()->dicts);
1080 if (result_mp == NULL) {
1081 result_mp = (PyDictObject *)Nuitka_GC_New(&PyDict_Type);
1083 Nuitka_Py_NewReference((PyObject *)result_mp);
1087#if PYTHON_VERSION < 0x3d0
1088 PyDictObject **items = tstate->interp->dict_state.free_list;
1089 int *numfree = &tstate->interp->dict_state.numfree;
1091 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
1092 struct _Py_dict_freelist *state = &freelists->dicts;
1093 PyDictObject **items = state->items;
1094 int *numfree = &state->numfree;
1099 result_mp = items[*numfree];
1101 Nuitka_Py_NewReference((PyObject *)result_mp);
1105 result_mp = (PyDictObject *)Nuitka_GC_New(&PyDict_Type);
1108 result_mp = (PyDictObject *)Nuitka_GC_New(&PyDict_Type);
1110 CHECK_OBJECT(result_mp);
1111 assert(PyDict_CheckExact((PyObject *)result_mp));
1116#if PYTHON_VERSION >= 0x360
1117static PyDictKeysObject *_Nuitka_AllocatePyDictKeysObject(PyThreadState *tstate, Py_ssize_t keys_size) {
1119 PyDictKeysObject *dk;
1124#if NUITKA_DICT_HAS_FREELIST && 0
1125#if PYTHON_VERSION < 0x3d0
1126 PyDictKeysObject **items = tstate->interp->dict_state.keys_free_list;
1127 int *numfree = &tstate->interp->dict_state.keys_numfree;
1129 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
1130 struct _Py_dictkeys_freelist *state = &freelists->dictkeys;
1131 PyDictKeysObject **items = state->items;
1132 int *numfree = &state->numfree;
1137 dk = items[*numfree];
1141#if PYTHON_VERSION < 0x3d0
1142 dk = (PyDictKeysObject *)NuitkaObject_Malloc(keys_size);
1144 dk = (PyDictKeysObject *)NuitkaMem_Malloc(keys_size);
1152#if PYTHON_VERSION >= 0x360 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT)
1155#define DK_USABLE_FRACTION(n) (((n) << 1) / 3)
1157static Py_ssize_t _Nuitka_Py_PyDict_KeysSize(PyDictKeysObject *keys) {
1158#if PYTHON_VERSION < 0x360
1159 return sizeof(PyDictKeysObject) + (DK_SIZE(keys) - 1) *
sizeof(PyDictKeyEntry);
1160#elif PYTHON_VERSION < 0x370
1161 return (
sizeof(PyDictKeysObject) - Py_MEMBER_SIZE(PyDictKeysObject, dk_indices) + DK_IXSIZE(keys) * DK_SIZE(keys) +
1162 DK_USABLE_FRACTION(DK_SIZE(keys)) *
sizeof(PyDictKeyEntry));
1163#elif PYTHON_VERSION < 0x3b0
1164 return (
sizeof(PyDictKeysObject) + DK_IXSIZE(keys) * DK_SIZE(keys) +
1165 DK_USABLE_FRACTION(DK_SIZE(keys)) *
sizeof(PyDictKeyEntry));
1167 size_t entry_size = keys->dk_kind == DICT_KEYS_GENERAL ?
sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
1168 return (
sizeof(PyDictKeysObject) + ((
size_t)1 << keys->dk_log2_index_bytes) +
1169 DK_USABLE_FRACTION(DK_SIZE(keys)) * entry_size);
1174#if PYTHON_VERSION < 0x3b0
1175typedef PyObject *PyDictValues;
1178#if PYTHON_VERSION < 0x360
1179#define DK_ENTRIES_SIZE(keys) (keys->dk_size)
1180#elif PYTHON_VERSION < 0x3b0
1181#define DK_ENTRIES_SIZE(keys) DK_USABLE_FRACTION(DK_SIZE(keys))
1183#define DK_ENTRIES_SIZE(keys) (keys->dk_nentries)
1187#if PYTHON_VERSION < 0x360
1188#define IS_COMPACT(dict_mp) (dict_mp->ma_used >= (dict_mp->ma_keys->dk_size * 2) / 3)
1190#define IS_COMPACT(dict_mp) (dict_mp->ma_used >= (dict_mp->ma_keys->dk_nentries * 2) / 3)
1193static inline PyDictValues *_Nuitka_PyDict_new_values(Py_ssize_t size) {
1194#if PYTHON_VERSION < 0x3b0
1195 Py_ssize_t values_size =
sizeof(PyObject *) * size;
1197 return (PyDictValues *)NuitkaMem_Malloc(values_size);
1198#elif PYTHON_VERSION < 0x3d0
1199 Py_ssize_t values_size =
sizeof(PyObject *) * size;
1202 size_t prefix_size = _Py_SIZE_ROUND_UP(size + 2,
sizeof(PyObject *));
1203 size_t n = prefix_size + values_size;
1204 uint8_t *mem = (uint8_t *)NuitkaMem_Malloc(n);
1205 assert(mem != NULL);
1207 assert(prefix_size %
sizeof(PyObject *) == 0);
1208 mem[prefix_size - 1] = (uint8_t)prefix_size;
1210 return (PyDictValues *)(mem + prefix_size);
1213 size_t suffix_size = _Py_SIZE_ROUND_UP(size,
sizeof(PyObject *));
1214 assert(suffix_size < 128);
1215 assert(suffix_size %
sizeof(PyObject *) == 0);
1216 size_t n = (size + 1) *
sizeof(PyObject *) + suffix_size;
1217 PyDictValues *result = (PyDictValues *)NuitkaMem_Malloc(n);
1219 result->embedded = 0;
1222 result->capacity = (uint8_t)size;
1227#if PYTHON_VERSION >= 0x3d0
1229static PyDictValues *_Nuitka_PyDict_copy_values(PyDictValues *values) {
1230 PyDictValues *new_values = _Nuitka_PyDict_new_values(values->capacity);
1231 if (unlikely(new_values == NULL)) {
1235 new_values->size = values->size;
1237 uint8_t *values_order = get_insertion_order_array(values);
1238 uint8_t *new_values_order = get_insertion_order_array(new_values);
1240 memcpy(new_values_order, values_order, values->capacity);
1242 for (
int i = 0; i < values->capacity; i++) {
1243 new_values->values[i] = values->values[i];
1245 assert(new_values->embedded == 0);
1250#include "HelpersDictionariesGenerated.c"
1252void DICT_CLEAR(PyObject *dict) {
1254 assert(PyDict_CheckExact(dict));
1261#if PYTHON_VERSION >= 0x3b0
1262static inline int Nuitka_py_get_index_from_order(PyDictObject *mp, Py_ssize_t i) {
1263 assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
1264#if PYTHON_VERSION < 0x3d0
1265 assert(i < (((
char *)mp->ma_values)[-2]));
1266 return ((
char *)mp->ma_values)[-3 - i];
1268 assert(i < mp->ma_values->size);
1269 uint8_t *array = get_insertion_order_array(mp->ma_values);
1275#if PYTHON_VERSION >= 0x3b0
1277static inline Py_ssize_t Nuitka_Py_dictkeys_get_index(
const PyDictKeysObject *keys, Py_ssize_t i) {
1278 int log2size = DK_LOG_SIZE(keys);
1282 ix = LOAD_INDEX(keys, 8, i);
1284 }
else if (log2size < 16) {
1285 ix = LOAD_INDEX(keys, 16, i);
1287#if SIZEOF_VOID_P > 4
1288 else if (log2size >= 32) {
1289 ix = LOAD_INDEX(keys, 64, i);
1293 ix = LOAD_INDEX(keys, 32, i);
1296 assert(ix >= DKIX_DUMMY);
1301#define PERTURB_SHIFT 5
1304#if PYTHON_VERSION >= 0x3d0
1306static inline Py_ALWAYS_INLINE Py_ssize_t Nuitka_Py_dictkeys_do_lookup(
1307 PyDictObject *mp, PyDictKeysObject *dk, PyObject *key, Py_hash_t hash,
1308 int (*check_lookup)(PyDictObject *, PyDictKeysObject *,
void *, Py_ssize_t ix, PyObject *key, Py_hash_t)) {
1309 void *ep0 = _DK_ENTRIES(dk);
1310 size_t mask = DK_MASK(dk);
1311 size_t perturb = hash;
1312 size_t i = (size_t)hash & mask;
1315 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1317 int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1323 }
else if (ix == DKIX_EMPTY) {
1326 perturb >>= PERTURB_SHIFT;
1327 i = mask & (i * 5 + perturb + 1);
1330 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1332 int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1338 }
else if (ix == DKIX_EMPTY) {
1341 perturb >>= PERTURB_SHIFT;
1342 i = mask & (i * 5 + perturb + 1);
1344 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_dictkeys_do_lookup failed");
1347static inline int Nuitka_Py_dictkeys_compare_unicode_generic(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0,
1348 Py_ssize_t ix, PyObject *key, Py_hash_t hash) {
1349 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1350 assert(ep->me_key != NULL);
1351 assert(PyUnicode_CheckExact(ep->me_key));
1352 assert(!PyUnicode_CheckExact(key));
1354 if (Nuitka_Py_unicode_get_hash(ep->me_key) == hash) {
1355 PyObject *startkey = ep->me_key;
1356 Py_INCREF(startkey);
1357 int cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(startkey, key);
1358 Py_DECREF(startkey);
1362 if (dk == mp->ma_keys && ep->me_key == startkey) {
1366 return DKIX_KEY_CHANGED;
1372static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1374 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_generic);
1377static inline int Nuitka_Py_dictkeys_compare_generic(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1378 PyObject *key, Py_hash_t hash) {
1379 PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1380 assert(ep->me_key != NULL);
1381 if (ep->me_key == key) {
1384 if (ep->me_hash == hash) {
1385 PyObject *startkey = ep->me_key;
1386 Py_INCREF(startkey);
1387 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1388 Py_DECREF(startkey);
1392 if (dk == mp->ma_keys && ep->me_key == startkey) {
1396 return DKIX_KEY_CHANGED;
1403static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1405 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_generic);
1408static inline int Nuitka_Py_dictkeys_compare_unicode_unicode(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0,
1409 Py_ssize_t ix, PyObject *key, Py_hash_t hash) {
1410 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1411 PyObject *ep_key = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key);
1412 assert(ep_key != NULL);
1413 assert(PyUnicode_CheckExact(ep_key));
1414 if (ep_key == key ||
1415 (Nuitka_Py_unicode_get_hash(ep_key) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep_key, key))) {
1421Py_ssize_t _Py_HOT_FUNCTION Nuitka_Py_unicodekeys_lookup_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash) {
1422 return Nuitka_Py_dictkeys_do_lookup(NULL, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_unicode);
1425#ifdef Py_GIL_DISABLED
1427static inline Py_ALWAYS_INLINE
int
1428Nuitka_Py_dictkeys_compare_unicode_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1429 PyObject *key, Py_hash_t hash) {
1430 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1431 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1432 assert(startkey == NULL || PyUnicode_CheckExact(ep->me_key));
1433 assert(!PyUnicode_CheckExact(key));
1435 if (startkey != NULL) {
1436 if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1437 return DKIX_KEY_CHANGED;
1440 if (Nuitka_Py_unicode_get_hash(startkey) == hash) {
1441 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1442 Py_DECREF(startkey);
1446 if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) &&
1447 startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1451 return DKIX_KEY_CHANGED;
1454 Py_DECREF(startkey);
1461static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1463 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_generic_threadsafe);
1466static inline Py_ALWAYS_INLINE
int
1467Nuitka_Py_dictkeys_compare_unicode_unicode_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1468 PyObject *key, Py_hash_t hash) {
1469 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1470 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1471 assert(startkey == NULL || PyUnicode_CheckExact(startkey));
1472 if (startkey == key) {
1475 if (startkey != NULL) {
1476 if (_Py_IsImmortal(startkey)) {
1477 return Nuitka_Py_unicode_get_hash(startkey) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(startkey, key);
1479 if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1480 return DKIX_KEY_CHANGED;
1482 if (Nuitka_Py_unicode_get_hash(startkey) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(startkey, key)) {
1483 Py_DECREF(startkey);
1486 Py_DECREF(startkey);
1492static Py_ssize_t _Py_HOT_FUNCTION Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(PyDictKeysObject *dk, PyObject *key,
1494 return Nuitka_Py_dictkeys_do_lookup(NULL, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_unicode_threadsafe);
1497static inline Py_ALWAYS_INLINE
int Nuitka_Py_dictkeys_compare_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
1498 void *ep0, Py_ssize_t ix,
1499 PyObject *key, Py_hash_t hash) {
1500 PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1501 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1502 if (startkey == key) {
1505 Py_ssize_t ep_hash = _Py_atomic_load_ssize_relaxed(&ep->me_hash);
1506 if (ep_hash == hash) {
1507 if (startkey == NULL || !_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1508 return DKIX_KEY_CHANGED;
1510 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1511 Py_DECREF(startkey);
1515 if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) && startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1519 return DKIX_KEY_CHANGED;
1525static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup_threadsafe(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1527 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_generic_threadsafe);
1530static inline void Nuitka_Py_dict_ensure_shared_on_read(PyDictObject *mp) {
1531 if (!_Py_IsOwnedByCurrentThread((PyObject *)mp) && !IS_DICT_SHARED(mp)) {
1536 Py_BEGIN_CRITICAL_SECTION(mp);
1537 if (!IS_DICT_SHARED(mp)) {
1538 SET_DICT_SHARED(mp);
1540 Py_END_CRITICAL_SECTION();
1544Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr) {
1545 PyDictKeysObject *dk;
1550 Nuitka_Py_dict_ensure_shared_on_read(mp);
1552 dk = _Py_atomic_load_ptr(&mp->ma_keys);
1555 if (kind != DICT_KEYS_GENERAL) {
1556 if (PyUnicode_CheckExact(key)) {
1557 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1559 ix = Nuitka_Py_unicodekeys_lookup_generic_threadsafe(mp, dk, key, hash);
1561 if (ix == DKIX_KEY_CHANGED) {
1566 if (kind == DICT_KEYS_SPLIT) {
1567 PyDictValues *values = _Py_atomic_load_ptr(&mp->ma_values);
1571 uint8_t capacity = _Py_atomic_load_uint8_relaxed(&values->capacity);
1572 if (ix >= (Py_ssize_t)capacity)
1575 value = _Py_TryXGetRef(&values->values[ix]);
1579 if (values != _Py_atomic_load_ptr(&mp->ma_values)) {
1584 value = _Py_TryXGetRef(&DK_UNICODE_ENTRIES(dk)[ix].me_value);
1585 if (value == NULL) {
1589 if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1598 ix = Nuitka_Py_dictkeys_generic_lookup_threadsafe(mp, dk, key, hash);
1599 if (ix == DKIX_KEY_CHANGED) {
1603 value = _Py_TryXGetRef(&DK_ENTRIES(dk)[ix].me_value);
1607 if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1616 *value_addr = value;
1624 Py_BEGIN_CRITICAL_SECTION(mp);
1625 ix = _Py_dict_lookup(mp, key, hash, &value);
1626 *value_addr = value;
1627 if (value != NULL) {
1629 _Py_NewRefWithLock(value);
1631 Py_END_CRITICAL_SECTION();
1637Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr) {
1638 Py_ssize_t ix = Nuitka_PyDictLookup(mp, key, hash, &value_addr);
1639 Py_XNewRef(*value_addr);
1645Py_ssize_t Nuitka_PyDictLookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1646 PyDictKeysObject *dk;
1650 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1653 kind = (DictKeysKind)dk->dk_kind;
1655 if (kind != DICT_KEYS_GENERAL) {
1656 if (PyUnicode_CheckExact(key)) {
1657#ifdef Py_GIL_DISABLED
1658 if (kind == DICT_KEYS_SPLIT) {
1659 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1661 if (ix == DKIX_KEY_CHANGED) {
1663 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1669 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1673 LOCK_KEYS_IF_SPLIT(dk, kind);
1675 ix = Nuitka_Py_unicodekeys_lookup_generic(mp, dk, key, hash);
1677 UNLOCK_KEYS_IF_SPLIT(dk, kind);
1678 DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1681 if (ix == DKIX_KEY_CHANGED) {
1687 if (kind == DICT_KEYS_SPLIT) {
1688 *value_addr = &mp->ma_values->values[ix];
1690 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1696 ix = Nuitka_Py_dictkeys_generic_lookup(mp, dk, key, hash);
1699 if (ix == DKIX_KEY_CHANGED) {
1704 *value_addr = &DK_ENTRIES(dk)[ix].me_value;
1714static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1716 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
1718 size_t mask = DK_MASK(dk);
1719 size_t perturb = hash;
1720 size_t i = (size_t)hash & mask;
1723 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1726 PyDictUnicodeEntry *ep = &ep0[ix];
1728 assert(ep->me_key != NULL);
1729 assert(PyUnicode_CheckExact(ep->me_key));
1731 if (ep->me_key == key) {
1735 if (Nuitka_Py_unicode_get_hash(ep->me_key) == hash) {
1736 PyObject *startkey = ep->me_key;
1737 Py_INCREF(startkey);
1738 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_UNICODE_OBJECT(startkey, key);
1739 Py_DECREF(startkey);
1741 if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
1745 if (dk == mp->ma_keys && ep->me_key == startkey) {
1746 if (cmp == NUITKA_BOOL_TRUE) {
1751 return DKIX_KEY_CHANGED;
1754 }
else if (ix == DKIX_EMPTY) {
1757 perturb >>= PERTURB_SHIFT;
1758 i = mask & (i * 5 + perturb + 1);
1761 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_unicodekeys_lookup_generic failed");
1764Py_ssize_t Nuitka_Py_unicodekeys_lookup_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash) {
1765 assert(PyUnicode_CheckExact(key));
1766 assert(dk->dk_kind != DICT_KEYS_GENERAL);
1768 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
1770 size_t mask = DK_MASK(dk);
1771 size_t perturb = hash;
1772 size_t i = (size_t)hash & mask;
1775 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1779 PyDictUnicodeEntry *ep = &ep0[ix];
1780 assert(ep->me_key != NULL);
1781 assert(PyUnicode_CheckExact(ep->me_key));
1783 if (ep->me_key == key || (Nuitka_Py_unicode_get_hash(ep->me_key) == hash &&
1784 RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep->me_key, key))) {
1787 }
else if (ix == DKIX_EMPTY) {
1790 perturb >>= PERTURB_SHIFT;
1792 i = mask & (i * 5 + perturb + 1);
1793 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1796 PyDictUnicodeEntry *ep = &ep0[ix];
1798 assert(ep->me_key != NULL);
1799 assert(PyUnicode_CheckExact(ep->me_key));
1801 if (ep->me_key == key || (Nuitka_Py_unicode_get_hash(ep->me_key) == hash &&
1802 RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep->me_key, key))) {
1805 }
else if (ix == DKIX_EMPTY) {
1809 perturb >>= PERTURB_SHIFT;
1810 i = mask & (i * 5 + perturb + 1);
1813 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_unicodekeys_lookup_unicode failed");
1817static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1819 PyDictKeyEntry *ep0 = DK_ENTRIES(dk);
1821 size_t mask = DK_MASK(dk);
1822 size_t perturb = hash;
1823 size_t i = (size_t)hash & mask;
1826 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1829 PyDictKeyEntry *ep = &ep0[ix];
1830 assert(ep->me_key != NULL);
1831 if (ep->me_key == key) {
1834 if (ep->me_hash == hash) {
1835 PyObject *startkey = ep->me_key;
1836 Py_INCREF(startkey);
1837 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(startkey, key);
1838 Py_DECREF(startkey);
1840 if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
1843 if (dk == mp->ma_keys && ep->me_key == startkey) {
1844 if (cmp == NUITKA_BOOL_TRUE) {
1849 return DKIX_KEY_CHANGED;
1852 }
else if (ix == DKIX_EMPTY) {
1855 perturb >>= PERTURB_SHIFT;
1856 i = mask & (i * 5 + perturb + 1);
1860Py_ssize_t Nuitka_PyDictLookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1861 PyDictKeysObject *dk;
1865 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1868 kind = (DictKeysKind)dk->dk_kind;
1870 if (kind != DICT_KEYS_GENERAL) {
1871 if (PyUnicode_CheckExact(key)) {
1872#ifdef Py_GIL_DISABLED
1873 if (kind == DICT_KEYS_SPLIT) {
1874 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1876 if (ix == DKIX_KEY_CHANGED) {
1878 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1884 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1888 LOCK_KEYS_IF_SPLIT(dk, kind);
1890 ix = Nuitka_Py_unicodekeys_lookup_generic(mp, dk, key, hash);
1892 UNLOCK_KEYS_IF_SPLIT(dk, kind);
1893 DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1896 if (ix == DKIX_KEY_CHANGED) {
1902 if (kind == DICT_KEYS_SPLIT) {
1903 *value_addr = &mp->ma_values->values[ix];
1905 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1911 ix = Nuitka_Py_dictkeys_generic_lookup(mp, dk, key, hash);
1914 if (ix == DKIX_KEY_CHANGED) {
1919 *value_addr = &DK_ENTRIES(dk)[ix].me_value;
1929Py_ssize_t Nuitka_PyDictLookupStr(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1930 assert(PyUnicode_CheckExact(key));
1932 PyDictKeysObject *dk = mp->ma_keys;
1933 assert(dk->dk_kind != DICT_KEYS_GENERAL);
1935 Py_ssize_t ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1938 if (dk->dk_kind == DICT_KEYS_SPLIT) {
1939 *value_addr = &mp->ma_values->values[ix];
1941 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1952bool Nuitka_DictNext(PyObject *dict, Py_ssize_t *pos, PyObject **key_ptr, PyObject **value_ptr) {
1954 assert(PyDict_CheckExact(dict));
1955 assert(key_ptr != NULL);
1956 assert(value_ptr != NULL);
1958#if PYTHON_VERSION < 0x300
1959 Py_ssize_t i = *pos;
1961 PyDictEntry *ep = ((PyDictObject *)dict)->ma_table;
1962 Py_ssize_t mask = ((PyDictObject *)dict)->ma_mask;
1964 while (i <= mask && ep[i].me_value == NULL) {
1974 *key_ptr = ep[i].me_key;
1975 *value_ptr = ep[i].me_value;
1979#elif PYTHON_VERSION < 0x360
1980 PyDictObject *mp = (PyDictObject *)dict;
1981 PyObject **dict_value_ptr;
1984 Py_ssize_t i = *pos;
1987 if (mp->ma_values) {
1988 dict_value_ptr = &mp->ma_values[i];
1989 offset =
sizeof(PyObject *);
1991 dict_value_ptr = &mp->ma_keys->dk_entries[i].me_value;
1992 offset =
sizeof(PyDictKeyEntry);
1995 Py_ssize_t mask = DK_MASK(mp->ma_keys);
1997 while ((i <= mask) && (*dict_value_ptr == NULL)) {
1998 dict_value_ptr = (PyObject **)(((
char *)dict_value_ptr) + offset);
2006 *key_ptr = mp->ma_keys->dk_entries[i].me_key;
2007 *value_ptr = *dict_value_ptr;
2012#elif PYTHON_VERSION < 0x3b0
2013 PyDictObject *mp = (PyDictObject *)dict;
2014 PyDictKeyEntry *entry;
2017 Py_ssize_t i = *pos;
2020 if (mp->ma_values) {
2021 if (i >= mp->ma_used) {
2025 entry = &DK_ENTRIES(mp->ma_keys)[i];
2026 value = DK_VALUE(mp, i);
2028 assert(value != NULL);
2030 Py_ssize_t n = mp->ma_keys->dk_nentries;
2036 entry = &DK_ENTRIES(mp->ma_keys)[i];
2038 while (i < n && entry->me_value == NULL) {
2047 value = entry->me_value;
2052 *key_ptr = entry->me_key;
2057 PyDictObject *mp = (PyDictObject *)dict;
2058 Py_ssize_t i = *pos;
2059 PyObject *key, *value;
2061 if (mp->ma_values) {
2063 assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
2065 if (i >= mp->ma_used) {
2069 int index = Nuitka_py_get_index_from_order(mp, i);
2070 value = mp->ma_values->values[index];
2072 key = DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key;
2074 assert(value != NULL);
2076 Py_ssize_t n = mp->ma_keys->dk_nentries;
2084 if (DK_IS_UNICODE(mp->ma_keys)) {
2085 PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
2087 while (i < n && entry_ptr->me_value == NULL) {
2096 key = entry_ptr->me_key;
2097 value = entry_ptr->me_value;
2099 PyDictKeyEntry *entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
2101 while (i < n && entry_ptr->me_value == NULL) {
2110 key = entry_ptr->me_key;
2111 value = entry_ptr->me_value;
2124PyObject *TO_DICT(PyThreadState *tstate, PyObject *seq_obj, PyObject *dict_obj) {
2127 if (seq_obj != NULL) {
2128 CHECK_OBJECT(seq_obj);
2131 if (PyDict_CheckExact(seq_obj)) {
2132 result = DICT_COPY(tstate, seq_obj);
2134 result = MAKE_DICT_EMPTY(tstate);
2138#if PYTHON_VERSION >= 0x300
2139 int res = HAS_ATTR_BOOL2(tstate, seq_obj, const_str_plain_keys);
2141 if (unlikely(res == -1)) {
2146 int res = HAS_ATTR_BOOL(tstate, seq_obj, const_str_plain_keys) ? 1 : 0;
2150 res = PyDict_Merge(result, seq_obj, 1);
2152 res = PyDict_MergeFromSeq2(result, seq_obj, 1);
2157 if (unlikely(res == -1)) {
2162 result = MAKE_DICT_EMPTY(tstate);
2167 if (dict_obj != NULL) {
2168 CHECK_OBJECT(dict_obj);
2170 int res = PyDict_Merge(result, dict_obj, 1);
2172 if (unlikely(res == -1)) {
2180#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
2181uint64_t nuitka_dict_version_tag_counter = ((uint64_t)1) << 32;
2184#if NUITKA_DICT_HAS_FREELIST
2185PyObject *MAKE_DICT_EMPTY(PyThreadState *tstate) {
2186 PyDictObject *empty_dict_mp = (PyDictObject *)const_dict_empty;
2188#if PYTHON_VERSION < 0x3c0
2189 empty_dict_mp->ma_keys->dk_refcnt++;
2192 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
2194 result_mp->ma_keys = empty_dict_mp->ma_keys;
2195 result_mp->ma_values = empty_dict_mp->ma_values;
2196 result_mp->ma_used = 0;
2197#if PYTHON_VERSION < 0x3e0
2198#if PYTHON_VERSION >= 0x3c0
2199 result_mp->ma_version_tag = DICT_NEXT_VERSION(_PyInterpreterState_GET());
2200#elif PYTHON_VERSION >= 0x360
2201 result_mp->ma_version_tag = 1;
2206#if defined(Py_REF_DEBUG) && PYTHON_VERSION < 0x3c0
2211 return (PyObject *)result_mp;
2215PyObject *MAKE_DICT(PyObject **pairs, Py_ssize_t size) {
2216 PyObject *result = _PyDict_NewPresized(size);
2220 for (Py_ssize_t i = 0; i < size; i++) {
2221 PyObject *key = pairs[i * 2];
2222 PyObject *value = pairs[i * 2 + 1];
2224 int res = PyDict_SetItem(result, key, value);
2226 if (unlikely(res != 0)) {
2235PyObject *MAKE_DICT_X(PyObject **pairs, Py_ssize_t size) {
2236 PyObject *result = _PyDict_NewPresized(size);
2240 for (Py_ssize_t i = 0; i < size; i++) {
2241 PyObject *value = pairs[i * 2 + 1];
2243 if (value != NULL) {
2244 PyObject *key = pairs[i * 2];
2246 CHECK_OBJECT(value);
2248 int res = PyDict_SetItem(result, key, value);
2250 if (unlikely(res != 0)) {
2260PyObject *MAKE_DICT_X_CSTR(
char const **keys, PyObject **values, Py_ssize_t size) {
2261 PyObject *result = _PyDict_NewPresized(size);
2265 for (Py_ssize_t i = 0; i < size; i++) {
2266 PyObject *value = values[i];
2268 if (value != NULL) {
2269 CHECK_OBJECT(value);
2271 int res = PyDict_SetItemString(result, keys[i], value);
2273 if (unlikely(res != 0)) {
Definition exceptions.h:712
Definition HelpersDictionaries.c:909
Definition HelpersDictionaries.c:1012