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 NuitkaMem_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 ASSERT_KEYS_LOCKED(keys) assert(PyMutex_IsLocked(&keys->dk_mutex))
84#define LOAD_SHARED_KEY(key) _Py_atomic_load_ptr_acquire(&key)
85#define STORE_SHARED_KEY(key, value) _Py_atomic_store_ptr_release(&key, value)
87#define INCREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, 1)
89#define DECREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, -1)
90#define LOAD_KEYS_NENTRIES(keys) _Py_atomic_load_ssize_relaxed(&keys->dk_nentries)
92static inline void Nuitka_Py_dictkeys_incref(PyDictKeysObject *dk) {
93 if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) {
97 _Py_IncRefTotal(_PyThreadState_GET());
102static inline void Nuitka_Py_dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk,
bool use_qsbr) {
103 if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) {
106 assert(FT_ATOMIC_LOAD_SSIZE(dk->dk_refcnt) > 0);
108 _Py_DecRefTotal(_PyThreadState_GET());
110 if (DECREF_KEYS(dk) == 1) {
111 if (DK_IS_UNICODE(dk)) {
112 PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dk);
114 for (i = 0, n = dk->dk_nentries; i < n; i++) {
115 Py_XDECREF(entries[i].me_key);
116 Py_XDECREF(entries[i].me_value);
119 PyDictKeyEntry *entries = DK_ENTRIES(dk);
121 for (i = 0, n = dk->dk_nentries; i < n; i++) {
122 Py_XDECREF(entries[i].me_key);
123 Py_XDECREF(entries[i].me_value);
126 Nuitka_Py_dictkeys_free_keys_object(dk, use_qsbr);
130#define INCREF_KEYS_FT(dk) Nuitka_Py_dictkeys_incref(dk)
131#define DECREF_KEYS_FT(dk, shared) Nuitka_Py_dictkeys_decref(_PyInterpreterState_GET(), dk, shared)
133static inline void split_keys_entry_added(PyDictKeysObject *keys) {
134 ASSERT_KEYS_LOCKED(keys);
138 _Py_atomic_store_ssize_relaxed(&keys->dk_nentries, keys->dk_nentries + 1);
139 _Py_atomic_store_ssize_release(&keys->dk_usable, keys->dk_usable - 1);
144#define ASSERT_DICT_LOCKED(op)
145#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
146#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
147#define ASSERT_KEYS_LOCKED(keys)
148#define LOAD_SHARED_KEY(key) key
149#define STORE_SHARED_KEY(key, value) key = value
150#define INCREF_KEYS(dk) dk->dk_refcnt++
151#define DECREF_KEYS(dk) dk->dk_refcnt--
152#define LOAD_KEYS_NENTRIES(keys) keys->dk_nentries
153#define INCREF_KEYS_FT(dk)
154#define DECREF_KEYS_FT(dk, shared)
155#define LOCK_KEYS_IF_SPLIT(keys, kind)
156#define UNLOCK_KEYS_IF_SPLIT(keys, kind)
157#define IS_DICT_SHARED(mp) (false)
158#define SET_DICT_SHARED(mp)
159#define LOAD_INDEX(keys, size, idx) ((const int##size##_t *)(keys->dk_indices))[idx]
160#define STORE_INDEX(keys, size, idx, value) ((int##size##_t *)(keys->dk_indices))[idx] = (int##size##_t)value
163Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
165PyObject *DICT_GET_ITEM0(PyThreadState *tstate, PyObject *dict, PyObject *key) {
167 assert(PyDict_Check(dict));
174#if PYTHON_VERSION < 0x300
175 if (PyString_CheckExact(key)) {
176 hash = ((PyStringObject *)key)->ob_shash;
178 if (unlikely(hash == -1)) {
179 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
182 if (unlikely(hash == -1)) {
186 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
188 if (unlikely(hash == -1)) {
193 PyDictObject *dict_object = (PyDictObject *)dict;
194 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
196 if (unlikely(entry == NULL || entry->me_value == NULL)) {
200 CHECK_OBJECT(entry->me_value);
201 return entry->me_value;
203 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
204 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
206 if (unlikely(hash == -1)) {
211 PyDictObject *dict_object = (PyDictObject *)dict;
213#if PYTHON_VERSION < 0x360
214 PyObject **value_addr;
215 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
217 if (unlikely(entry == NULL || *value_addr == NULL)) {
221#if PYTHON_VERSION < 0x370
222 PyObject **value_addr;
223 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
224#elif PYTHON_VERSION < 0x3b0
226 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
227#elif defined(Py_GIL_DISABLED)
229 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
231 PyObject **value_addr;
232 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
235 if (unlikely(ix < 0)) {
240#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
241 assert(value_addr != NULL);
242 PyObject *result = *value_addr;
244 if (unlikely(result == NULL)) {
248 CHECK_OBJECT(result);
253PyObject *DICT_GET_ITEM1(PyThreadState *tstate, PyObject *dict, PyObject *key) {
255 assert(PyDict_Check(dict));
262#if PYTHON_VERSION < 0x300
263 if (PyString_CheckExact(key)) {
264 hash = ((PyStringObject *)key)->ob_shash;
266 if (unlikely(hash == -1)) {
267 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
270 if (unlikely(hash == -1)) {
274 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
276 if (unlikely(hash == -1)) {
281 PyDictObject *dict_object = (PyDictObject *)dict;
282 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
284 if (unlikely(entry == NULL || entry->me_value == NULL)) {
288 CHECK_OBJECT(entry->me_value);
289 Py_INCREF(entry->me_value);
290 return entry->me_value;
292 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
293 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
295 if (unlikely(hash == -1)) {
300 PyDictObject *dict_object = (PyDictObject *)dict;
302#if PYTHON_VERSION < 0x360
303 PyObject **value_addr;
304 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
306 if (unlikely(entry == NULL || *value_addr == NULL)) {
310#if PYTHON_VERSION < 0x370
311 PyObject **value_addr;
312 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
313#elif PYTHON_VERSION < 0x3b0
315 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
316#elif defined(Py_GIL_DISABLED)
318 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
320 PyObject **value_addr;
321 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
324 if (unlikely(ix < 0)) {
329#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
330 assert(value_addr != NULL);
331 PyObject *result = *value_addr;
333 if (unlikely(result == NULL)) {
337 CHECK_OBJECT(result);
343#if PYTHON_VERSION >= 0x3c0
344static PyObject *Nuitka_CreateKeyError(PyThreadState *tstate, PyObject *key) {
345 return (PyObject *)Nuitka_BaseExceptionSingleArg_new(tstate, (PyTypeObject *)PyExc_KeyError, key);
349static void SET_CURRENT_EXCEPTION_KEY_ERROR(PyThreadState *tstate, PyObject *key) {
350#if PYTHON_VERSION < 0x3c0
355 if (PyTuple_Check(key) || key == Py_None) {
356 PyObject *tuple = MAKE_TUPLE1(tstate, key);
358 SET_CURRENT_EXCEPTION_TYPE0_VALUE1(tstate, PyExc_KeyError, tuple);
360 SET_CURRENT_EXCEPTION_TYPE0_VALUE0(tstate, PyExc_KeyError, key);
365 RESTORE_ERROR_OCCURRED_STATE(tstate, &exception_state);
376PyObject *DICT_GET_ITEM_WITH_ERROR(PyThreadState *tstate, PyObject *dict, PyObject *key) {
378 assert(PyDict_CheckExact(dict));
385#if PYTHON_VERSION < 0x300
386 if (PyString_CheckExact(key)) {
387 hash = ((PyStringObject *)key)->ob_shash;
389 if (unlikely(hash == -1)) {
390 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
393 if (unlikely(hash == -1)) {
397 hash = HASH_VALUE_WITH_ERROR(tstate, key);
399 if (unlikely(hash == -1)) {
404 PyDictObject *dict_object = (PyDictObject *)dict;
405 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
407 if (unlikely(entry == NULL || entry->me_value == NULL)) {
408 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
413 CHECK_OBJECT(entry->me_value);
414 Py_INCREF(entry->me_value);
415 return entry->me_value;
417 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
418 hash = HASH_VALUE_WITH_ERROR(tstate, key);
419 if (unlikely(hash == -1)) {
424 PyDictObject *dict_object = (PyDictObject *)dict;
426#if PYTHON_VERSION < 0x360
427 PyObject **value_addr;
428 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
430 if (unlikely(entry == NULL || *value_addr == NULL)) {
431 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
435 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
440#if PYTHON_VERSION < 0x370
441 PyObject **value_addr;
442 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
443#elif PYTHON_VERSION < 0x3b0
445 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
446#elif defined(Py_GIL_DISABLED)
448 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
450 PyObject **value_addr;
451 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
454 if (unlikely(ix < 0)) {
455 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
459 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
465#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
466 assert(value_addr != NULL);
467 PyObject *result = *value_addr;
470 if (unlikely(result == NULL)) {
471 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
475 SET_CURRENT_EXCEPTION_KEY_ERROR(tstate, key);
480 CHECK_OBJECT(result);
486PyObject *DICT_GET_ITEM_WITH_HASH_ERROR0(PyThreadState *tstate, PyObject *dict, PyObject *key) {
488 assert(PyDict_CheckExact(dict));
495#if PYTHON_VERSION < 0x300
496 if (PyString_CheckExact(key)) {
497 hash = ((PyStringObject *)key)->ob_shash;
499 if (unlikely(hash == -1)) {
500 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
503 if (unlikely(hash == -1)) {
507 hash = HASH_VALUE_WITH_ERROR(tstate, key);
509 if (unlikely(hash == -1)) {
514 PyDictObject *dict_object = (PyDictObject *)dict;
515 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
517 if (unlikely(entry == NULL || entry->me_value == NULL)) {
521 CHECK_OBJECT(entry->me_value);
522 return entry->me_value;
524 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
525 hash = HASH_VALUE_WITH_ERROR(tstate, key);
526 if (unlikely(hash == -1)) {
531 PyDictObject *dict_object = (PyDictObject *)dict;
533#if PYTHON_VERSION < 0x360
534 PyObject **value_addr;
535 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
537 if (unlikely(entry == NULL || *value_addr == NULL)) {
541#if PYTHON_VERSION < 0x370
542 PyObject **value_addr;
543 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
544#elif PYTHON_VERSION < 0x3b0
546 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
547#elif defined(Py_GIL_DISABLED)
549 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
551 PyObject **value_addr;
552 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
555 if (unlikely(ix < 0)) {
560#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
561 assert(value_addr != NULL);
562 PyObject *result = *value_addr;
565 if (unlikely(result == NULL)) {
569 CHECK_OBJECT(result);
577PyObject *DICT_GET_ITEM_WITH_HASH_ERROR1(PyThreadState *tstate, PyObject *dict, PyObject *key) {
579 assert(PyDict_CheckExact(dict));
586#if PYTHON_VERSION < 0x300
587 if (PyString_CheckExact(key)) {
588 hash = ((PyStringObject *)key)->ob_shash;
590 if (unlikely(hash == -1)) {
591 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
594 if (unlikely(hash == -1)) {
598 hash = HASH_VALUE_WITH_ERROR(tstate, key);
600 if (unlikely(hash == -1)) {
605 PyDictObject *dict_object = (PyDictObject *)dict;
606 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
608 if (unlikely(entry == NULL || entry->me_value == NULL)) {
612 CHECK_OBJECT(entry->me_value);
613 Py_INCREF(entry->me_value);
614 return entry->me_value;
616 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
617 hash = HASH_VALUE_WITH_ERROR(tstate, key);
618 if (unlikely(hash == -1)) {
623 PyDictObject *dict_object = (PyDictObject *)dict;
625#if PYTHON_VERSION < 0x360
626 PyObject **value_addr;
627 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
629 if (unlikely(entry == NULL || *value_addr == NULL)) {
633#if PYTHON_VERSION < 0x370
634 PyObject **value_addr;
635 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
636#elif PYTHON_VERSION < 0x3b0
638 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
639#elif defined(Py_GIL_DISABLED)
641 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
643 PyObject **value_addr;
644 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
647 if (unlikely(ix < 0)) {
652#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
653 assert(value_addr != NULL);
654 PyObject *result = *value_addr;
657 if (unlikely(result == NULL)) {
661 CHECK_OBJECT(result);
667int DICT_HAS_ITEM(PyThreadState *tstate, PyObject *dict, PyObject *key) {
669 assert(PyDict_Check(dict));
676#if PYTHON_VERSION < 0x300
677 if (PyString_CheckExact(key)) {
678 hash = ((PyStringObject *)key)->ob_shash;
680 if (unlikely(hash == -1)) {
681 hash = HASH_VALUE_WITHOUT_ERROR(tstate, key);
684 if (unlikely(hash == -1)) {
688 hash = HASH_VALUE_WITH_ERROR(tstate, key);
690 if (unlikely(hash == -1)) {
695 PyDictObject *dict_object = (PyDictObject *)dict;
696 PyDictEntry *entry = (dict_object->ma_lookup)(dict_object, key, hash);
698 if (unlikely(entry == NULL || entry->me_value == NULL)) {
704 if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *)key)->hash) == -1) {
705 hash = HASH_VALUE_WITH_ERROR(tstate, key);
706 if (unlikely(hash == -1)) {
711 PyDictObject *dict_object = (PyDictObject *)dict;
713#if PYTHON_VERSION < 0x360
714 PyObject **value_addr;
715 PyDictKeyEntry *entry = dict_object->ma_keys->dk_lookup(dict_object, key, hash, &value_addr);
717 if (unlikely(entry == NULL || *value_addr == NULL)) {
723#if PYTHON_VERSION < 0x370
724 PyObject **value_addr;
725 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &value_addr, NULL);
726#elif PYTHON_VERSION < 0x3b0
728 Py_ssize_t ix = (dict_object->ma_keys->dk_lookup)(dict_object, key, hash, &result);
729#elif defined(Py_GIL_DISABLED)
731 Py_ssize_t ix = Nuitka_Py_dict_lookup_threadsafe(dict_object, key, hash, &result);
733 PyObject **value_addr;
734 Py_ssize_t ix = Nuitka_PyDictLookup(dict_object, key, hash, &value_addr);
737 if (unlikely(ix < 0)) {
738 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
745#if PYTHON_VERSION < 0x370 || (PYTHON_VERSION >= 0x3b0 && !defined(Py_GIL_DISABLED))
746 assert(value_addr != NULL);
747 PyObject *result = *value_addr;
750 if (unlikely(result == NULL)) {
758#if PYTHON_VERSION < 0x300
759PyObject *DICT_ITEMS(PyObject *dict) {
761 assert(PyDict_Check(dict));
763 PyDictObject *mp = (PyDictObject *)dict;
774 result = MAKE_LIST_EMPTY(tstate, size);
775 CHECK_OBJECT(result);
777 for (Py_ssize_t i = 0; i < size; i++) {
779 PyObject *item = MAKE_TUPLE_EMPTY(tstate, 2);
782 PyList_SET_ITEM(result, i, item);
785 if (unlikely(size != mp->ma_used)) {
792 PyDictEntry *ep = mp->ma_table;
793 Py_ssize_t mask = mp->ma_mask;
795 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
796 PyObject *value = ep[i].me_value;
798 PyObject *key = ep[i].me_key;
799 PyObject *item = PyList_GET_ITEM(result, j);
800 PyTuple_SET_ITEM0(item, 0, key);
801 PyTuple_SET_ITEM0(item, 1, value);
807 assert(PyList_GET_SIZE(result) == size);
812#if PYTHON_VERSION < 0x300
813PyObject *DICT_KEYS(PyObject *dict) {
815 assert(PyDict_Check(dict));
817 PyDictObject *mp = (PyDictObject *)dict;
828 result = MAKE_LIST_EMPTY(tstate, size);
829 CHECK_OBJECT(result);
831 if (unlikely(size != mp->ma_used)) {
838 PyDictEntry *ep = mp->ma_table;
839 Py_ssize_t mask = mp->ma_mask;
841 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
842 PyObject *value = ep[i].me_value;
844 PyObject *key = ep[i].me_key;
845 PyList_SET_ITEM0(result, j, key);
851 assert(PyList_GET_SIZE(result) == size);
857#if PYTHON_VERSION < 0x300
858PyObject *DICT_VALUES(PyObject *dict) {
860 assert(PyDict_Check(dict));
862 PyDictObject *mp = (PyDictObject *)dict;
873 result = MAKE_LIST_EMPTY(tstate, size);
874 CHECK_OBJECT(result);
876 if (unlikely(size != mp->ma_used)) {
883 PyDictEntry *ep = mp->ma_table;
884 Py_ssize_t mask = mp->ma_mask;
886 for (Py_ssize_t i = 0, j = 0; i <= mask; i++) {
887 PyObject *value = ep[i].me_value;
889 PyList_SET_ITEM0(result, j, value);
895 assert(PyList_GET_SIZE(result) == size);
903#if PYTHON_VERSION < 0x300
905 PyObject_HEAD PyDictObject *di_dict;
913#if PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x350
915 PyObject_HEAD PyDictObject *dv_dict;
921static inline PyObject *_MAKE_DICT_ITERATOR(PyThreadState *tstate, PyDictObject *dict, PyTypeObject *type,
923 CHECK_OBJECT((PyObject *)dict);
924 assert(PyDict_CheckExact((PyObject *)dict));
926#if PYTHON_VERSION < 0x300
931 di->di_used = dict->ma_used;
933 di->len = dict->ma_used;
936 di->di_result = MAKE_TUPLE2(tstate, Py_None, Py_None);
937 CHECK_OBJECT(di->di_result);
939 di->di_result = NULL;
943 return (PyObject *)di;
945 _PyDictViewObject *dv = (_PyDictViewObject *)Nuitka_GC_New(type);
952 return (PyObject *)dv;
956PyObject *DICT_ITERITEMS(PyThreadState *tstate, PyObject *dict) {
957#if PYTHON_VERSION < 0x270
958 static PyTypeObject *dictiteritems_type = NULL;
960 if (unlikely(dictiteritems_type == NULL)) {
962 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"iteritems")));
965 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictiteritems_type,
true);
966#elif PYTHON_VERSION < 0x300
967 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterItem_Type,
true);
969 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictItems_Type,
true);
973PyObject *DICT_ITERKEYS(PyThreadState *tstate, PyObject *dict) {
974#if PYTHON_VERSION < 0x270
975 static PyTypeObject *dictiterkeys_type = NULL;
977 if (unlikely(dictiterkeys_type == NULL)) {
979 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"iterkeys")));
982 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictiterkeys_type,
false);
983#elif PYTHON_VERSION < 0x300
984 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterKey_Type,
false);
986 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictKeys_Type,
false);
990PyObject *DICT_ITERVALUES(PyThreadState *tstate, PyObject *dict) {
991#if PYTHON_VERSION < 0x270
992 static PyTypeObject *dictitervalues_type = NULL;
994 if (unlikely(dictitervalues_type == NULL)) {
995 dictitervalues_type =
996 Py_TYPE(CALL_FUNCTION_NO_ARGS(tstate, PyObject_GetAttrString(const_dict_empty,
"itervalues")));
999 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, dictitervalues_type,
false);
1000#elif PYTHON_VERSION < 0x300
1001 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictIterValue_Type,
false);
1003 return _MAKE_DICT_ITERATOR(tstate, (PyDictObject *)dict, &PyDictValues_Type,
false);
1008 PyObject_HEAD PyDictObject *dv_dict;
1011static PyObject *_MAKE_DICT_VIEW(PyDictObject *dict, PyTypeObject *type) {
1012 CHECK_OBJECT((PyObject *)dict);
1013 assert(PyDict_CheckExact((PyObject *)dict));
1019 dv->dv_dict = (PyDictObject *)dict;
1020 Nuitka_GC_Track(dv);
1021 return (PyObject *)dv;
1024PyObject *DICT_VIEWKEYS(PyObject *dict) {
1025#if PYTHON_VERSION < 0x270
1026 static PyTypeObject *dictkeysview_type = NULL;
1028 if (unlikely(dictkeysview_type)) {
1029 dictkeysview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewkeys")));
1032 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictkeysview_type);
1034 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictKeys_Type);
1038PyObject *DICT_VIEWVALUES(PyObject *dict) {
1039#if PYTHON_VERSION < 0x270
1040 static PyTypeObject *dictvaluesview_type = NULL;
1042 if (unlikely(dictvaluesview_type)) {
1043 dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewvalues")));
1046 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type);
1048 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictValues_Type);
1052PyObject *DICT_VIEWITEMS(PyObject *dict) {
1053#if PYTHON_VERSION < 0x270
1054 static PyTypeObject *dictvaluesview_type = NULL;
1056 if (unlikely(dictvaluesview_type)) {
1057 dictvaluesview_type = Py_TYPE(PyObject_GetIter(PyObject_GetAttrString(const_dict_empty,
"viewitems")));
1060 return _MAKE_DICT_VIEW((PyDictObject *)dict, dictvaluesview_type);
1062 return _MAKE_DICT_VIEW((PyDictObject *)dict, &PyDictItems_Type);
1066#if PYTHON_VERSION >= 0x3e0
1067static PyDictObject *_Nuitka_AllocatePyDictObjectFresh(
void) {
1068 size_t pre_size = _PyType_PreHeaderSize(&PyDict_Type);
1069 size_t size = _PyObject_SIZE(&PyDict_Type);
1071 char *alloc = (
char *)NuitkaObject_Malloc(size + pre_size);
1072 assert(alloc != NULL);
1074 ((PyObject **)alloc)[0] = NULL;
1075 ((PyObject **)alloc)[1] = NULL;
1077 PyObject *obj = (PyObject *)(alloc + pre_size);
1079 Nuitka_PyObject_GC_Link(obj);
1080 _PyObject_Init(obj, &PyDict_Type);
1082 return (PyDictObject *)obj;
1086#if PYTHON_VERSION >= 0x300 && (NUITKA_DICT_HAS_FREELIST || !_NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT)
1087static PyDictObject *_Nuitka_AllocatePyDictObject(PyThreadState *tstate) {
1088 PyDictObject *result_mp;
1090#if NUITKA_DICT_HAS_FREELIST
1091#if PYTHON_VERSION < 0x3d0
1093 PyDictObject **items = tstate->interp->dict_state.free_list;
1094 int *numfree = &tstate->interp->dict_state.numfree;
1095#elif PYTHON_VERSION < 0x3e0
1096 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
1097 struct _Py_dict_freelist *state = &freelists->dicts;
1098 PyDictObject **items = state->items;
1099 int *numfree = &state->numfree;
1102#if PYTHON_VERSION >= 0x3e0
1103 struct _Py_freelists *freelists = Nuitka_Py_freelists_GET(tstate);
1105 result_mp = (PyDictObject *)Nuitka_PyFreeList_Pop(&freelists->dicts);
1107 if (result_mp != NULL) {
1108 Nuitka_Py_NewReference((PyObject *)result_mp);
1110 result_mp = _Nuitka_AllocatePyDictObjectFresh();
1115 result_mp = items[*numfree];
1117 Nuitka_Py_NewReference((PyObject *)result_mp);
1119#if PYTHON_VERSION >= 0x3e0
1120 result_mp = _Nuitka_AllocatePyDictObjectFresh();
1122 result_mp = (PyDictObject *)Nuitka_GC_New(&PyDict_Type);
1127#if PYTHON_VERSION >= 0x3e0
1128 result_mp = _Nuitka_AllocatePyDictObjectFresh();
1130 result_mp = (PyDictObject *)Nuitka_GC_New(&PyDict_Type);
1133#if PYTHON_VERSION >= 0x3e0
1134 result_mp->_ma_watcher_tag = 0;
1137 CHECK_OBJECT(result_mp);
1138 assert(PyDict_CheckExact((PyObject *)result_mp));
1143#if PYTHON_VERSION >= 0x360
1144static PyDictKeysObject *_Nuitka_AllocatePyDictKeysObject(PyThreadState *tstate, Py_ssize_t keys_size) {
1146 PyDictKeysObject *dk;
1151#if NUITKA_DICT_HAS_FREELIST && 0
1152#if PYTHON_VERSION < 0x3d0
1153 PyDictKeysObject **items = tstate->interp->dict_state.keys_free_list;
1154 int *numfree = &tstate->interp->dict_state.keys_numfree;
1156 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
1157 struct _Py_dictkeys_freelist *state = &freelists->dictkeys;
1158 PyDictKeysObject **items = state->items;
1159 int *numfree = &state->numfree;
1164 dk = items[*numfree];
1168#if PYTHON_VERSION < 0x3d0
1169 dk = (PyDictKeysObject *)NuitkaObject_Malloc(keys_size);
1171 dk = (PyDictKeysObject *)NuitkaMem_Malloc(keys_size);
1179#if PYTHON_VERSION >= 0x360 && !_NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT
1182#define DK_USABLE_FRACTION(n) (((n) << 1) / 3)
1184static Py_ssize_t _Nuitka_Py_PyDict_KeysSize(PyDictKeysObject *keys) {
1185#if PYTHON_VERSION < 0x360
1186 return sizeof(PyDictKeysObject) + (DK_SIZE(keys) - 1) *
sizeof(PyDictKeyEntry);
1187#elif PYTHON_VERSION < 0x370
1188 return (
sizeof(PyDictKeysObject) - Py_MEMBER_SIZE(PyDictKeysObject, dk_indices) + DK_IXSIZE(keys) * DK_SIZE(keys) +
1189 DK_USABLE_FRACTION(DK_SIZE(keys)) *
sizeof(PyDictKeyEntry));
1190#elif PYTHON_VERSION < 0x3b0
1191 return (
sizeof(PyDictKeysObject) + DK_IXSIZE(keys) * DK_SIZE(keys) +
1192 DK_USABLE_FRACTION(DK_SIZE(keys)) *
sizeof(PyDictKeyEntry));
1194 size_t entry_size = keys->dk_kind == DICT_KEYS_GENERAL ?
sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
1195 return (
sizeof(PyDictKeysObject) + ((
size_t)1 << keys->dk_log2_index_bytes) +
1196 DK_USABLE_FRACTION(DK_SIZE(keys)) * entry_size);
1201#if PYTHON_VERSION < 0x3b0
1202typedef PyObject *PyDictValues;
1205#if PYTHON_VERSION < 0x360
1206#define DK_ENTRIES_SIZE(keys) (keys->dk_size)
1207#elif PYTHON_VERSION < 0x3b0
1208#define DK_ENTRIES_SIZE(keys) DK_USABLE_FRACTION(DK_SIZE(keys))
1210#define DK_ENTRIES_SIZE(keys) (keys->dk_nentries)
1214#if PYTHON_VERSION < 0x360
1215#define IS_COMPACT(dict_mp) (dict_mp->ma_used >= (dict_mp->ma_keys->dk_size * 2) / 3)
1217#define IS_COMPACT(dict_mp) (dict_mp->ma_used >= (dict_mp->ma_keys->dk_nentries * 2) / 3)
1220static inline PyDictValues *_Nuitka_PyDict_new_values(Py_ssize_t size) {
1221#if PYTHON_VERSION < 0x3b0
1222 Py_ssize_t values_size =
sizeof(PyObject *) * size;
1224 return (PyDictValues *)NuitkaMem_Malloc(values_size);
1225#elif PYTHON_VERSION < 0x3d0
1226 Py_ssize_t values_size =
sizeof(PyObject *) * size;
1229 size_t prefix_size = _Py_SIZE_ROUND_UP(size + 2,
sizeof(PyObject *));
1230 size_t n = prefix_size + values_size;
1231 uint8_t *mem = (uint8_t *)NuitkaMem_Malloc(n);
1232 assert(mem != NULL);
1234 assert(prefix_size %
sizeof(PyObject *) == 0);
1235 mem[prefix_size - 1] = (uint8_t)prefix_size;
1237 return (PyDictValues *)(mem + prefix_size);
1240 size_t suffix_size = _Py_SIZE_ROUND_UP(size,
sizeof(PyObject *));
1241 assert(suffix_size < 128);
1242 assert(suffix_size %
sizeof(PyObject *) == 0);
1243 size_t n = (size + 1) *
sizeof(PyObject *) + suffix_size;
1244 PyDictValues *result = (PyDictValues *)NuitkaMem_Malloc(n);
1246 result->embedded = 0;
1249 result->capacity = (uint8_t)size;
1254#if PYTHON_VERSION >= 0x3d0
1256static PyDictValues *_Nuitka_PyDict_copy_values(PyDictValues *values) {
1257 PyDictValues *new_values = _Nuitka_PyDict_new_values(values->capacity);
1258 if (unlikely(new_values == NULL)) {
1262 new_values->size = values->size;
1264 uint8_t *values_order = get_insertion_order_array(values);
1265 uint8_t *new_values_order = get_insertion_order_array(new_values);
1267 memcpy(new_values_order, values_order, values->capacity);
1269 for (
int i = 0; i < values->capacity; i++) {
1270 new_values->values[i] = values->values[i];
1272 assert(new_values->embedded == 0);
1277#include "HelpersDictionariesGenerated.c"
1279void DICT_CLEAR(PyObject *dict) {
1281 assert(PyDict_CheckExact(dict));
1288#if PYTHON_VERSION >= 0x3b0
1289static inline int Nuitka_py_get_index_from_order(PyDictObject *mp, Py_ssize_t i) {
1290 assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
1291#if PYTHON_VERSION < 0x3d0
1292 assert(i < (((
char *)mp->ma_values)[-2]));
1293 return ((
char *)mp->ma_values)[-3 - i];
1295 assert(i < mp->ma_values->size);
1296 uint8_t *array = get_insertion_order_array(mp->ma_values);
1302#if PYTHON_VERSION >= 0x3b0
1304static inline Py_ssize_t Nuitka_Py_dictkeys_get_index(
const PyDictKeysObject *keys, Py_ssize_t i) {
1305 int log2size = DK_LOG_SIZE(keys);
1309 ix = LOAD_INDEX(keys, 8, i);
1311 }
else if (log2size < 16) {
1312 ix = LOAD_INDEX(keys, 16, i);
1314#if SIZEOF_VOID_P > 4
1315 else if (log2size >= 32) {
1316 ix = LOAD_INDEX(keys, 64, i);
1320 ix = LOAD_INDEX(keys, 32, i);
1323 assert(ix >= DKIX_DUMMY);
1328#define PERTURB_SHIFT 5
1331#if PYTHON_VERSION >= 0x3d0
1333static inline Py_ALWAYS_INLINE Py_ssize_t Nuitka_Py_dictkeys_do_lookup(
1334 PyDictObject *mp, PyDictKeysObject *dk, PyObject *key, Py_hash_t hash,
1335 int (*check_lookup)(PyDictObject *, PyDictKeysObject *,
void *, Py_ssize_t ix, PyObject *key, Py_hash_t)) {
1336 void *ep0 = _DK_ENTRIES(dk);
1337 size_t mask = DK_MASK(dk);
1338 size_t perturb = hash;
1339 size_t i = (size_t)hash & mask;
1342 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1344 int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1350 }
else if (ix == DKIX_EMPTY) {
1353 perturb >>= PERTURB_SHIFT;
1354 i = mask & (i * 5 + perturb + 1);
1357 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1359 int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1365 }
else if (ix == DKIX_EMPTY) {
1368 perturb >>= PERTURB_SHIFT;
1369 i = mask & (i * 5 + perturb + 1);
1371 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_dictkeys_do_lookup failed");
1374static inline int Nuitka_Py_dictkeys_compare_unicode_generic(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0,
1375 Py_ssize_t ix, PyObject *key, Py_hash_t hash) {
1376 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1377 assert(ep->me_key != NULL);
1378 assert(PyUnicode_CheckExact(ep->me_key));
1379 assert(!PyUnicode_CheckExact(key));
1381 if (Nuitka_Py_unicode_get_hash(ep->me_key) == hash) {
1382 PyObject *startkey = ep->me_key;
1383 Py_INCREF(startkey);
1384 int cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(startkey, key);
1385 Py_DECREF(startkey);
1389 if (dk == mp->ma_keys && ep->me_key == startkey) {
1393 return DKIX_KEY_CHANGED;
1399static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1401 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_generic);
1404static inline int Nuitka_Py_dictkeys_compare_generic(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1405 PyObject *key, Py_hash_t hash) {
1406 PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1407 assert(ep->me_key != NULL);
1408 if (ep->me_key == key) {
1411 if (ep->me_hash == hash) {
1412 PyObject *startkey = ep->me_key;
1413 Py_INCREF(startkey);
1414 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1415 Py_DECREF(startkey);
1419 if (dk == mp->ma_keys && ep->me_key == startkey) {
1423 return DKIX_KEY_CHANGED;
1430static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1432 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_generic);
1435static inline int Nuitka_Py_dictkeys_compare_unicode_unicode(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0,
1436 Py_ssize_t ix, PyObject *key, Py_hash_t hash) {
1437 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1438 PyObject *ep_key = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key);
1439 assert(ep_key != NULL);
1440 assert(PyUnicode_CheckExact(ep_key));
1441 if (ep_key == key ||
1442 (Nuitka_Py_unicode_get_hash(ep_key) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep_key, key))) {
1448Py_ssize_t _Py_HOT_FUNCTION Nuitka_Py_unicodekeys_lookup_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash) {
1449 return Nuitka_Py_dictkeys_do_lookup(NULL, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_unicode);
1452#ifdef Py_GIL_DISABLED
1454static inline Py_ALWAYS_INLINE
int
1455Nuitka_Py_dictkeys_compare_unicode_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1456 PyObject *key, Py_hash_t hash) {
1457 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1458 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1459 assert(startkey == NULL || PyUnicode_CheckExact(ep->me_key));
1460 assert(!PyUnicode_CheckExact(key));
1462 if (startkey != NULL) {
1463 if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1464 return DKIX_KEY_CHANGED;
1467 if (Nuitka_Py_unicode_get_hash(startkey) == hash) {
1468 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1469 Py_DECREF(startkey);
1473 if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) &&
1474 startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1478 return DKIX_KEY_CHANGED;
1481 Py_DECREF(startkey);
1488static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1490 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_generic_threadsafe);
1493static inline Py_ALWAYS_INLINE
int
1494Nuitka_Py_dictkeys_compare_unicode_unicode_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
void *ep0, Py_ssize_t ix,
1495 PyObject *key, Py_hash_t hash) {
1496 PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1497 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1498 assert(startkey == NULL || PyUnicode_CheckExact(startkey));
1499 if (startkey == key) {
1502 if (startkey != NULL) {
1503 if (_Py_IsImmortal(startkey)) {
1504 return Nuitka_Py_unicode_get_hash(startkey) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(startkey, key);
1506 if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1507 return DKIX_KEY_CHANGED;
1509 if (Nuitka_Py_unicode_get_hash(startkey) == hash && RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(startkey, key)) {
1510 Py_DECREF(startkey);
1513 Py_DECREF(startkey);
1519static Py_ssize_t _Py_HOT_FUNCTION Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(PyDictKeysObject *dk, PyObject *key,
1521 return Nuitka_Py_dictkeys_do_lookup(NULL, dk, key, hash, Nuitka_Py_dictkeys_compare_unicode_unicode_threadsafe);
1524static inline Py_ALWAYS_INLINE
int Nuitka_Py_dictkeys_compare_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
1525 void *ep0, Py_ssize_t ix,
1526 PyObject *key, Py_hash_t hash) {
1527 PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1528 PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1529 if (startkey == key) {
1532 Py_ssize_t ep_hash = _Py_atomic_load_ssize_relaxed(&ep->me_hash);
1533 if (ep_hash == hash) {
1534 if (startkey == NULL || !_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1535 return DKIX_KEY_CHANGED;
1537 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1538 Py_DECREF(startkey);
1542 if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) && startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1546 return DKIX_KEY_CHANGED;
1552static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup_threadsafe(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1554 return Nuitka_Py_dictkeys_do_lookup(mp, dk, key, hash, Nuitka_Py_dictkeys_compare_generic_threadsafe);
1557static inline void Nuitka_Py_dict_ensure_shared_on_read(PyDictObject *mp) {
1558 if (!_Py_IsOwnedByCurrentThread((PyObject *)mp) && !IS_DICT_SHARED(mp)) {
1563 Py_BEGIN_CRITICAL_SECTION(mp);
1564 if (!IS_DICT_SHARED(mp)) {
1565 SET_DICT_SHARED(mp);
1567 Py_END_CRITICAL_SECTION();
1571Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr) {
1572 PyDictKeysObject *dk;
1577 Nuitka_Py_dict_ensure_shared_on_read(mp);
1579 dk = _Py_atomic_load_ptr(&mp->ma_keys);
1582 if (kind != DICT_KEYS_GENERAL) {
1583 if (PyUnicode_CheckExact(key)) {
1584 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1586 ix = Nuitka_Py_unicodekeys_lookup_generic_threadsafe(mp, dk, key, hash);
1588 if (ix == DKIX_KEY_CHANGED) {
1593 if (kind == DICT_KEYS_SPLIT) {
1594 PyDictValues *values = _Py_atomic_load_ptr(&mp->ma_values);
1598 uint8_t capacity = _Py_atomic_load_uint8_relaxed(&values->capacity);
1599 if (ix >= (Py_ssize_t)capacity)
1602 value = _Py_TryXGetRef(&values->values[ix]);
1606 if (values != _Py_atomic_load_ptr(&mp->ma_values)) {
1611 value = _Py_TryXGetRef(&DK_UNICODE_ENTRIES(dk)[ix].me_value);
1612 if (value == NULL) {
1616 if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1625 ix = Nuitka_Py_dictkeys_generic_lookup_threadsafe(mp, dk, key, hash);
1626 if (ix == DKIX_KEY_CHANGED) {
1630 value = _Py_TryXGetRef(&DK_ENTRIES(dk)[ix].me_value);
1634 if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1643 *value_addr = value;
1651 Py_BEGIN_CRITICAL_SECTION(mp);
1652 PyObject **locked_value_addr = NULL;
1653 ix = Nuitka_PyDictLookup(mp, key, hash, &locked_value_addr);
1654 value = locked_value_addr == NULL ? NULL : *locked_value_addr;
1655 *value_addr = value;
1656 if (value != NULL) {
1658 _Py_NewRefWithLock(value);
1660 Py_END_CRITICAL_SECTION();
1666Py_ssize_t Nuitka_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr) {
1667 Py_ssize_t ix = Nuitka_PyDictLookup(mp, key, hash, &value_addr);
1668 Py_XNewRef(*value_addr);
1674Py_ssize_t Nuitka_PyDictLookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1675 PyDictKeysObject *dk;
1679 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1682 kind = (DictKeysKind)dk->dk_kind;
1684 if (kind != DICT_KEYS_GENERAL) {
1685 if (PyUnicode_CheckExact(key)) {
1686#ifdef Py_GIL_DISABLED
1687 if (kind == DICT_KEYS_SPLIT) {
1688 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1690 if (ix == DKIX_KEY_CHANGED) {
1692 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1698 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1702 LOCK_KEYS_IF_SPLIT(dk, kind);
1704 ix = Nuitka_Py_unicodekeys_lookup_generic(mp, dk, key, hash);
1706 UNLOCK_KEYS_IF_SPLIT(dk, kind);
1707 DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1710 if (ix == DKIX_KEY_CHANGED) {
1716 if (kind == DICT_KEYS_SPLIT) {
1717 *value_addr = &mp->ma_values->values[ix];
1719 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1725 ix = Nuitka_Py_dictkeys_generic_lookup(mp, dk, key, hash);
1728 if (ix == DKIX_KEY_CHANGED) {
1733 *value_addr = &DK_ENTRIES(dk)[ix].me_value;
1743static Py_ssize_t Nuitka_Py_unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1745 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
1747 size_t mask = DK_MASK(dk);
1748 size_t perturb = hash;
1749 size_t i = (size_t)hash & mask;
1752 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1755 PyDictUnicodeEntry *ep = &ep0[ix];
1757 assert(ep->me_key != NULL);
1758 assert(PyUnicode_CheckExact(ep->me_key));
1760 if (ep->me_key == key) {
1764 if (Nuitka_Py_unicode_get_hash(ep->me_key) == hash) {
1765 PyObject *startkey = ep->me_key;
1766 Py_INCREF(startkey);
1767 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_UNICODE_OBJECT(startkey, key);
1768 Py_DECREF(startkey);
1770 if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
1774 if (dk == mp->ma_keys && ep->me_key == startkey) {
1775 if (cmp == NUITKA_BOOL_TRUE) {
1780 return DKIX_KEY_CHANGED;
1783 }
else if (ix == DKIX_EMPTY) {
1786 perturb >>= PERTURB_SHIFT;
1787 i = mask & (i * 5 + perturb + 1);
1790 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_unicodekeys_lookup_generic failed");
1793Py_ssize_t Nuitka_Py_unicodekeys_lookup_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash) {
1794 assert(PyUnicode_CheckExact(key));
1795 assert(dk->dk_kind != DICT_KEYS_GENERAL);
1797 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
1799 size_t mask = DK_MASK(dk);
1800 size_t perturb = hash;
1801 size_t i = (size_t)hash & mask;
1804 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1808 PyDictUnicodeEntry *ep = &ep0[ix];
1809 assert(ep->me_key != NULL);
1810 assert(PyUnicode_CheckExact(ep->me_key));
1812 if (ep->me_key == key || (Nuitka_Py_unicode_get_hash(ep->me_key) == hash &&
1813 RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep->me_key, key))) {
1816 }
else if (ix == DKIX_EMPTY) {
1819 perturb >>= PERTURB_SHIFT;
1821 i = mask & (i * 5 + perturb + 1);
1822 ix = Nuitka_Py_dictkeys_get_index(dk, i);
1825 PyDictUnicodeEntry *ep = &ep0[ix];
1827 assert(ep->me_key != NULL);
1828 assert(PyUnicode_CheckExact(ep->me_key));
1830 if (ep->me_key == key || (Nuitka_Py_unicode_get_hash(ep->me_key) == hash &&
1831 RICH_COMPARE_EQ_CBOOL_UNICODE_UNICODE(ep->me_key, key))) {
1834 }
else if (ix == DKIX_EMPTY) {
1838 perturb >>= PERTURB_SHIFT;
1839 i = mask & (i * 5 + perturb + 1);
1842 NUITKA_CANNOT_GET_HERE(
"Nuitka_Py_unicodekeys_lookup_unicode failed");
1846static Py_ssize_t Nuitka_Py_dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key,
1848 PyDictKeyEntry *ep0 = DK_ENTRIES(dk);
1850 size_t mask = DK_MASK(dk);
1851 size_t perturb = hash;
1852 size_t i = (size_t)hash & mask;
1855 Py_ssize_t ix = Nuitka_Py_dictkeys_get_index(dk, i);
1858 PyDictKeyEntry *ep = &ep0[ix];
1859 assert(ep->me_key != NULL);
1860 if (ep->me_key == key) {
1863 if (ep->me_hash == hash) {
1864 PyObject *startkey = ep->me_key;
1865 Py_INCREF(startkey);
1866 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(startkey, key);
1867 Py_DECREF(startkey);
1869 if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
1872 if (dk == mp->ma_keys && ep->me_key == startkey) {
1873 if (cmp == NUITKA_BOOL_TRUE) {
1878 return DKIX_KEY_CHANGED;
1881 }
else if (ix == DKIX_EMPTY) {
1884 perturb >>= PERTURB_SHIFT;
1885 i = mask & (i * 5 + perturb + 1);
1889Py_ssize_t Nuitka_PyDictLookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1890 PyDictKeysObject *dk;
1894 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1897 kind = (DictKeysKind)dk->dk_kind;
1899 if (kind != DICT_KEYS_GENERAL) {
1900 if (PyUnicode_CheckExact(key)) {
1901#ifdef Py_GIL_DISABLED
1902 if (kind == DICT_KEYS_SPLIT) {
1903 ix = Nuitka_Py_unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1905 if (ix == DKIX_KEY_CHANGED) {
1907 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1913 ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1917 LOCK_KEYS_IF_SPLIT(dk, kind);
1919 ix = Nuitka_Py_unicodekeys_lookup_generic(mp, dk, key, hash);
1921 UNLOCK_KEYS_IF_SPLIT(dk, kind);
1922 DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1925 if (ix == DKIX_KEY_CHANGED) {
1931 if (kind == DICT_KEYS_SPLIT) {
1932 *value_addr = &mp->ma_values->values[ix];
1934 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1940 ix = Nuitka_Py_dictkeys_generic_lookup(mp, dk, key, hash);
1943 if (ix == DKIX_KEY_CHANGED) {
1948 *value_addr = &DK_ENTRIES(dk)[ix].me_value;
1958Py_ssize_t Nuitka_PyDictLookupStr(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr) {
1959 assert(PyUnicode_CheckExact(key));
1961 PyDictKeysObject *dk = mp->ma_keys;
1962 assert(dk->dk_kind != DICT_KEYS_GENERAL);
1964 Py_ssize_t ix = Nuitka_Py_unicodekeys_lookup_unicode(dk, key, hash);
1967 if (dk->dk_kind == DICT_KEYS_SPLIT) {
1968 *value_addr = &mp->ma_values->values[ix];
1970 *value_addr = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1981bool Nuitka_DictNext(PyObject *dict, Py_ssize_t *pos, PyObject **key_ptr, PyObject **value_ptr) {
1983 assert(PyDict_CheckExact(dict));
1984 assert(key_ptr != NULL);
1985 assert(value_ptr != NULL);
1987#if PYTHON_VERSION < 0x300
1988 Py_ssize_t i = *pos;
1990 PyDictEntry *ep = ((PyDictObject *)dict)->ma_table;
1991 Py_ssize_t mask = ((PyDictObject *)dict)->ma_mask;
1993 while (i <= mask && ep[i].me_value == NULL) {
2003 *key_ptr = ep[i].me_key;
2004 *value_ptr = ep[i].me_value;
2008#elif PYTHON_VERSION < 0x360
2009 PyDictObject *mp = (PyDictObject *)dict;
2010 PyObject **dict_value_ptr;
2013 Py_ssize_t i = *pos;
2016 if (mp->ma_values) {
2017 dict_value_ptr = &mp->ma_values[i];
2018 offset =
sizeof(PyObject *);
2020 dict_value_ptr = &mp->ma_keys->dk_entries[i].me_value;
2021 offset =
sizeof(PyDictKeyEntry);
2024 Py_ssize_t mask = DK_MASK(mp->ma_keys);
2026 while ((i <= mask) && (*dict_value_ptr == NULL)) {
2027 dict_value_ptr = (PyObject **)(((
char *)dict_value_ptr) + offset);
2035 *key_ptr = mp->ma_keys->dk_entries[i].me_key;
2036 *value_ptr = *dict_value_ptr;
2041#elif PYTHON_VERSION < 0x3b0
2042 PyDictObject *mp = (PyDictObject *)dict;
2043 PyDictKeyEntry *entry;
2046 Py_ssize_t i = *pos;
2049 if (mp->ma_values) {
2050 if (i >= mp->ma_used) {
2054 entry = &DK_ENTRIES(mp->ma_keys)[i];
2055 value = DK_VALUE(mp, i);
2057 assert(value != NULL);
2059 Py_ssize_t n = mp->ma_keys->dk_nentries;
2065 entry = &DK_ENTRIES(mp->ma_keys)[i];
2067 while (i < n && entry->me_value == NULL) {
2076 value = entry->me_value;
2081 *key_ptr = entry->me_key;
2086 PyDictObject *mp = (PyDictObject *)dict;
2087 Py_ssize_t i = *pos;
2088 PyObject *key, *value;
2090 if (mp->ma_values) {
2092 assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
2094 if (i >= mp->ma_used) {
2098 int index = Nuitka_py_get_index_from_order(mp, i);
2099 value = mp->ma_values->values[index];
2101 key = DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key;
2103 assert(value != NULL);
2105 Py_ssize_t n = mp->ma_keys->dk_nentries;
2113 if (DK_IS_UNICODE(mp->ma_keys)) {
2114 PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
2116 while (i < n && entry_ptr->me_value == NULL) {
2125 key = entry_ptr->me_key;
2126 value = entry_ptr->me_value;
2128 PyDictKeyEntry *entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
2130 while (i < n && entry_ptr->me_value == NULL) {
2139 key = entry_ptr->me_key;
2140 value = entry_ptr->me_value;
2153PyObject *TO_DICT(PyThreadState *tstate, PyObject *seq_obj, PyObject *dict_obj) {
2156 if (seq_obj != NULL) {
2157 CHECK_OBJECT(seq_obj);
2160 if (PyDict_CheckExact(seq_obj)) {
2161 result = DICT_COPY(tstate, seq_obj);
2163 result = MAKE_DICT_EMPTY(tstate);
2167#if PYTHON_VERSION >= 0x300
2168 int res = HAS_ATTR_BOOL2(tstate, seq_obj, const_str_plain_keys);
2170 if (unlikely(res == -1)) {
2175 int res = HAS_ATTR_BOOL(tstate, seq_obj, const_str_plain_keys) ? 1 : 0;
2179 res = PyDict_Merge(result, seq_obj, 1);
2181 res = PyDict_MergeFromSeq2(result, seq_obj, 1);
2186 if (unlikely(res == -1)) {
2191 result = MAKE_DICT_EMPTY(tstate);
2196 if (dict_obj != NULL) {
2197 CHECK_OBJECT(dict_obj);
2199 int res = PyDict_Merge(result, dict_obj, 1);
2201 if (unlikely(res == -1)) {
2209#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
2210uint64_t nuitka_dict_version_tag_counter = ((uint64_t)1) << 32;
2213#if NUITKA_DICT_HAS_FREELIST
2214PyObject *MAKE_DICT_EMPTY(PyThreadState *tstate) {
2215 PyDictObject *empty_dict_mp = (PyDictObject *)const_dict_empty;
2217#if PYTHON_VERSION < 0x3c0
2218 empty_dict_mp->ma_keys->dk_refcnt++;
2221 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
2223 result_mp->ma_keys = empty_dict_mp->ma_keys;
2224#if PYTHON_VERSION < 0x3b0
2225 result_mp->ma_values = empty_dict_mp->ma_values;
2227 assert(empty_dict_mp->ma_values == NULL);
2228 result_mp->ma_values = NULL;
2230 result_mp->ma_used = 0;
2231#if PYTHON_VERSION >= 0x3c0 && PYTHON_VERSION < 0x3e0
2232 result_mp->ma_version_tag = DICT_NEXT_VERSION(_PyInterpreterState_GET());
2233#elif PYTHON_VERSION >= 0x360 && PYTHON_VERSION < 0x3e0
2234 result_mp->ma_version_tag = 1;
2238#if PYTHON_VERSION < 0x3c0
2239 Nuitka_Py_IncRefTotal(tstate);
2243#if PYTHON_VERSION >= 0x3e0
2244 Nuitka_GC_Track(result_mp);
2247 return (PyObject *)result_mp;
2251PyObject *MAKE_DICT(PyObject **pairs, Py_ssize_t size) {
2252 PyObject *result = _PyDict_NewPresized(size);
2256 for (Py_ssize_t i = 0; i < size; i++) {
2257 PyObject *key = pairs[i * 2];
2258 PyObject *value = pairs[i * 2 + 1];
2260 int res = PyDict_SetItem(result, key, value);
2262 if (unlikely(res != 0)) {
2271PyObject *MAKE_DICT_X(PyObject **pairs, Py_ssize_t size) {
2272 PyObject *result = _PyDict_NewPresized(size);
2276 for (Py_ssize_t i = 0; i < size; i++) {
2277 PyObject *value = pairs[i * 2 + 1];
2279 if (value != NULL) {
2280 PyObject *key = pairs[i * 2];
2282 CHECK_OBJECT(value);
2284 int res = PyDict_SetItem(result, key, value);
2286 if (unlikely(res != 0)) {
2296PyObject *MAKE_DICT_X_CSTR(
char const **keys, PyObject **values, Py_ssize_t size) {
2297 PyObject *result = _PyDict_NewPresized(size);
2301 for (Py_ssize_t i = 0; i < size; i++) {
2302 PyObject *value = values[i];
2304 if (value != NULL) {
2305 CHECK_OBJECT(value);
2307 int res = PyDict_SetItemString(result, keys[i], value);
2309 if (unlikely(res != 0)) {
Definition exceptions.h:712
Definition HelpersDictionaries.c:904
Definition HelpersDictionaries.c:1007