3#ifndef __NUITKA_DICTIONARIES_H__
4#define __NUITKA_DICTIONARIES_H__
6static inline Py_ssize_t DICT_SIZE(PyObject *dict) {
8 assert(PyDict_CheckExact(dict));
10 return ((PyDictObject *)dict)->ma_used;
13static inline PyDictObject *MODULE_DICT(PyObject *module) {
16 PyDictObject *dict = (PyDictObject *)(((
PyModuleObject *)module)->md_dict);
21#if PYTHON_VERSION < 0x300
24typedef PyDictEntry *Nuitka_DictEntryHandle;
26static PyDictEntry *GET_STRING_DICT_ENTRY(PyDictObject *dict, Nuitka_StringObject *key) {
27 assert(PyDict_CheckExact(dict));
28 assert(Nuitka_String_CheckExact(key));
30 Py_hash_t hash = key->ob_shash;
34 if (unlikely(hash == -1)) {
35 hash = PyString_Type.tp_hash((PyObject *)key);
39 PyDictEntry *entry = dict->ma_lookup(dict, (PyObject *)key, hash);
43 assert(entry != NULL);
48NUITKA_MAY_BE_UNUSED
static PyObject *GET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle) {
return handle->me_value; }
50NUITKA_MAY_BE_UNUSED
static void SET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle, PyObject *value) {
51 handle->me_value = value;
54static PyObject *GET_STRING_DICT_VALUE(PyDictObject *dict, Nuitka_StringObject *key) {
55 return GET_STRING_DICT_ENTRY(dict, key)->me_value;
64#if PYTHON_VERSION < 0x3b0
73#if PYTHON_VERSION < 0x360
74typedef PyDictKeyEntry *(*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr);
75#elif PYTHON_VERSION < 0x370
76typedef Py_ssize_t (*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr,
79typedef Py_ssize_t (*dict_lookup_func)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
84#if PYTHON_VERSION < 0x3b0
86#define DK_SIZE(dk) ((dk)->dk_size)
87struct _dictkeysobject {
90 dict_lookup_func dk_lookup;
92#if PYTHON_VERSION < 0x360
93 PyDictKeyEntry dk_entries[1];
95 Py_ssize_t dk_nentries;
96#if PYTHON_VERSION < 0x370
114#if PYTHON_VERSION >= 0x360
116#if PYTHON_VERSION < 0x3b0
119#define DK_IXSIZE(dk) \
120 (DK_SIZE(dk) <= 0xff ? 1 : DK_SIZE(dk) <= 0xffff ? 2 : DK_SIZE(dk) <= 0xffffffff ? 4 : sizeof(int64_t))
122#define DK_IXSIZE(dk) (DK_SIZE(dk) <= 0xff ? 1 : DK_SIZE(dk) <= 0xffff ? 2 : sizeof(int32_t))
125#if PYTHON_VERSION < 0x370
126#define DK_ENTRIES(dk) ((PyDictKeyEntry *)(&(dk)->dk_indices.as_1[DK_SIZE(dk) * DK_IXSIZE(dk)]))
128#define DK_ENTRIES(dk) ((PyDictKeyEntry *)(&((int8_t *)((dk)->dk_indices))[DK_SIZE(dk) * DK_IXSIZE(dk)]))
134#define DK_ENTRIES(dk) (dk->dk_entries)
137#if PYTHON_VERSION < 0x3b0
138#define DK_VALUE(dk, i) dk->ma_values[i]
140#define DK_VALUE(dk, i) dk->ma_values->values[i]
143#define DK_MASK(dk) (DK_SIZE(dk) - 1)
145typedef PyObject **Nuitka_DictEntryHandle;
147#if PYTHON_VERSION >= 0x3b0
148extern Py_ssize_t Nuitka_Py_unicodekeys_lookup_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash);
150extern Py_ssize_t Nuitka_PyDictLookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr);
151extern Py_ssize_t Nuitka_PyDictLookupStr(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr);
154static inline Py_hash_t Nuitka_Py_unicode_get_hash(PyObject *o) {
155 assert(PyUnicode_CheckExact(o));
157 return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyUnicodeObject *)o)->_base._base.hash);
160static Nuitka_DictEntryHandle GET_STRING_DICT_ENTRY(PyDictObject *dict, Nuitka_StringObject *key) {
161 assert(PyDict_CheckExact(dict));
162 assert(Nuitka_String_CheckExact(key));
164 Py_hash_t hash = Nuitka_Py_unicode_get_hash((PyObject *)key);
169 hash = PyUnicode_Type.tp_hash((PyObject *)key);
172#if PYTHON_VERSION < 0x360
173 PyObject **value_addr;
175 PyDictKeyEntry *entry = dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value_addr);
179 assert(entry != NULL);
183#elif PYTHON_VERSION < 0x370
184 PyObject **value_addr;
187 dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value_addr,
192#elif PYTHON_VERSION < 0x3b0
195 Py_ssize_t ix = dict->ma_keys->dk_lookup(dict, (PyObject *)key, hash, &value);
199 }
else if (_PyDict_HasSplitTable(dict)) {
200 return &dict->ma_values[ix];
202 return &DK_ENTRIES(dict->ma_keys)[ix].me_value;
207 NUITKA_MAY_BE_UNUSED Py_ssize_t found;
211 if (unlikely(dict->ma_keys->dk_kind == DICT_KEYS_GENERAL)) {
212 found = Nuitka_PyDictLookup(dict, (PyObject *)key, hash, &value);
214 found = Nuitka_PyDictLookupStr(dict, (PyObject *)key, hash, &value);
217 assert(found != DKIX_ERROR);
223NUITKA_MAY_BE_UNUSED
static PyObject *GET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle) {
return *handle; }
225NUITKA_MAY_BE_UNUSED
static void SET_DICT_ENTRY_VALUE(Nuitka_DictEntryHandle handle, PyObject *value) {
229NUITKA_MAY_BE_UNUSED
static PyObject *GET_STRING_DICT_VALUE(PyDictObject *dict, Nuitka_StringObject *key) {
230 Nuitka_DictEntryHandle handle = GET_STRING_DICT_ENTRY(dict, key);
232#if PYTHON_VERSION >= 0x360
233 if (handle == NULL) {
238 return GET_DICT_ENTRY_VALUE(handle);
243NUITKA_MAY_BE_UNUSED
static bool DICT_SET_ITEM(PyObject *dict, PyObject *key, PyObject *value) {
245 assert(PyDict_Check(dict));
249 int status = PyDict_SetItem(dict, key, value);
251 if (unlikely(status != 0)) {
258NUITKA_MAY_BE_UNUSED
static bool DICT_REMOVE_ITEM(PyObject *dict, PyObject *key) {
259 int status = PyDict_DelItem(dict, key);
261 if (unlikely(status == -1)) {
269extern PyObject *DICT_GET_ITEM_WITH_ERROR(PyThreadState *tstate, PyObject *dict, PyObject *key);
272extern PyObject *DICT_GET_ITEM_WITH_HASH_ERROR1(PyThreadState *tstate, PyObject *dict, PyObject *key);
273extern PyObject *DICT_GET_ITEM_WITH_HASH_ERROR0(PyThreadState *tstate, PyObject *dict, PyObject *key);
276extern PyObject *DICT_GET_ITEM1(PyThreadState *tstate, PyObject *dict, PyObject *key);
277extern PyObject *DICT_GET_ITEM0(PyThreadState *tstate, PyObject *dict, PyObject *key);
280extern int DICT_HAS_ITEM(PyThreadState *tstate, PyObject *dict, PyObject *key);
283extern PyObject *TO_DICT(PyThreadState *tstate, PyObject *seq_obj, PyObject *dict_obj);
288#if PYTHON_VERSION >= 0x360 && PYTHON_VERSION <= 0x3c0
289#define _NUITKA_MAINTAIN_DICT_VERSION_TAG 1
292#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
293extern uint64_t nuitka_dict_version_tag_counter;
296NUITKA_MAY_BE_UNUSED
static void UPDATE_STRING_DICT0(PyDictObject *dict, Nuitka_StringObject *key, PyObject *value) {
299 Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key);
301#if PYTHON_VERSION >= 0x360
303 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
308 PyObject *old = GET_DICT_ENTRY_VALUE(entry);
315 if (likely(old != NULL)) {
317 SET_DICT_ENTRY_VALUE(entry, value);
319#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
320 dict->ma_version_tag = nuitka_dict_version_tag_counter++;
326 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
331NUITKA_MAY_BE_UNUSED
static void UPDATE_STRING_DICT_INPLACE(PyDictObject *dict, Nuitka_StringObject *key,
335 Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key);
337#if PYTHON_VERSION >= 0x360
339 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
348 PyObject *old = GET_DICT_ENTRY_VALUE(entry);
353 if (likely(old != NULL)) {
354 SET_DICT_ENTRY_VALUE(entry, value);
356#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
357 dict->ma_version_tag = nuitka_dict_version_tag_counter++;
360 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
371NUITKA_MAY_BE_UNUSED
static void UPDATE_STRING_DICT1(PyDictObject *dict, Nuitka_StringObject *key, PyObject *value) {
375 Nuitka_DictEntryHandle entry = GET_STRING_DICT_ENTRY(dict, key);
377#if PYTHON_VERSION >= 0x360
379 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
388 PyObject *old = GET_DICT_ENTRY_VALUE(entry);
394 if (likely(old != NULL)) {
395 SET_DICT_ENTRY_VALUE(entry, value);
397#if _NUITKA_MAINTAIN_DICT_VERSION_TAG
398 dict->ma_version_tag = nuitka_dict_version_tag_counter++;
402 DICT_SET_ITEM((PyObject *)dict, (PyObject *)key, value);
413#if PYTHON_VERSION < 0x300
415extern PyObject *DICT_KEYS(PyObject *dict);
417extern PyObject *DICT_VALUES(PyObject *dict);
419extern PyObject *DICT_ITEMS(PyObject *dict);
423extern PyObject *DICT_ITERKEYS(PyThreadState *tstate, PyObject *dict);
426extern PyObject *DICT_ITERVALUES(PyThreadState *tstate, PyObject *dict);
429extern PyObject *DICT_ITERITEMS(PyThreadState *tstate, PyObject *dict);
432extern PyObject *DICT_VIEWKEYS(PyObject *dict);
435extern PyObject *DICT_VIEWVALUES(PyObject *dict);
438extern PyObject *DICT_VIEWITEMS(PyObject *dict);
441extern PyObject *DICT_COPY(PyThreadState *tstate, PyObject *dict);
444extern void DICT_CLEAR(PyObject *dict);
447extern bool Nuitka_DictNext(PyObject *dict, Py_ssize_t *pos, PyObject **key_ptr, PyObject **value_ptr);
449#if PYTHON_VERSION >= 0x3a0 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_FREELIST_ALL) && \
450 !defined(_NUITKA_EXPERIMENTAL_DISABLE_FREELIST_DICT)
451#define NUITKA_DICT_HAS_FREELIST 1
454extern PyObject *MAKE_DICT_EMPTY(PyThreadState *tstate);
456#define NUITKA_DICT_HAS_FREELIST 0
457static inline PyObject *MAKE_DICT_EMPTY(PyThreadState *tstate) {
460 PyObject *result = PyDict_New();
461 assert(result != NULL);
467extern PyObject *MAKE_DICT(PyObject **pairs, Py_ssize_t size);
469extern PyObject *MAKE_DICT_X(PyObject **pairs, Py_ssize_t size);
471extern PyObject *MAKE_DICT_X_CSTR(
char const **keys, PyObject **values, Py_ssize_t size);
474#if PYTHON_VERSION >= 0x3e0
476 PyObject_HEAD PyDictObject *di_dict;
Definition HelpersDictionaries.c:904