5#include "nuitka/prelude.h"
10PyObject *DICT_COPY(PyThreadState *tstate, PyObject *dict_value) {
11#if _NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT
12 CHECK_OBJECT(dict_value);
13 assert(PyDict_CheckExact(dict_value));
15 return PyDict_Copy(dict_value);
18 Py_BEGIN_CRITICAL_SECTION(dict_value);
20 CHECK_OBJECT(dict_value);
21 assert(PyDict_CheckExact(dict_value));
23 if (((PyDictObject *)dict_value)->ma_used == 0) {
24 result = MAKE_DICT_EMPTY(tstate);
26 PyDictObject *dict_mp = (PyDictObject *)dict_value;
28#if PYTHON_VERSION < 0x300
31 result = _PyDict_NewPresized(dict_mp->ma_used);
33 for (Py_ssize_t i = 0; i <= dict_mp->ma_mask; i++) {
34 PyDictEntry *entry = &dict_mp->ma_table[i];
36 if (entry->me_value != NULL) {
37 PyObject *key = entry->me_key;
39 PyObject *value = entry->me_value;
41 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
47 if (_PyDict_HasSplitTable(dict_mp)) {
48 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
49 assert(result_mp != NULL);
50 result = (PyObject *)result_mp;
52#if PYTHON_VERSION < 0x3b0
53 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
55 Py_ssize_t size = dict_mp->ma_keys->dk_nentries + dict_mp->ma_keys->dk_usable;
58#if PYTHON_VERSION < 0x3d0
59 PyDictValues *new_values = _Nuitka_PyDict_new_values(size);
60 assert(new_values != NULL);
62#if PYTHON_VERSION >= 0x3b0
64 size_t prefix_size = ((uint8_t *)new_values)[-1];
65 memcpy((
char *)new_values - prefix_size, (
char *)dict_mp->ma_values - prefix_size, prefix_size - 1);
68 PyDictValues *new_values = _Nuitka_PyDict_copy_values(dict_mp->ma_values);
69 assert(new_values != NULL);
70 size = new_values->capacity;
73 result_mp->ma_values = new_values;
74 result_mp->ma_keys = dict_mp->ma_keys;
75 result_mp->ma_used = dict_mp->ma_used;
77 Nuitka_Py_IncRefTotal(tstate);
78 dict_mp->ma_keys->dk_refcnt += 1;
80 for (Py_ssize_t i = 0; i < size; i++) {
81 if (DK_VALUE(dict_mp, i)) {
82 PyObject *value = DK_VALUE(dict_mp, i);
84 DK_VALUE(result_mp, i) = value;
88 DK_VALUE(result_mp, i) = NULL;
92 Nuitka_GC_Track(result_mp);
94#if PYTHON_VERSION >= 0x360 && !defined(Py_GIL_DISABLED)
98 if (dict_mp->ma_values == NULL && IS_COMPACT(dict_mp)) {
99 assert(dict_mp->ma_values == NULL);
100 assert(dict_mp->ma_keys->dk_refcnt == 1);
102 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
103 result = (PyObject *)result_mp;
105 result_mp->ma_values = NULL;
106 result_mp->ma_used = dict_mp->ma_used;
108 Py_ssize_t keys_size = _Nuitka_Py_PyDict_KeysSize(dict_mp->ma_keys);
109 result_mp->ma_keys = _Nuitka_AllocatePyDictKeysObject(tstate, keys_size);
110 assert(result_mp->ma_keys);
112 memcpy(result_mp->ma_keys, dict_mp->ma_keys, keys_size);
115#if PYTHON_VERSION < 0x3b0
116 PyDictKeyEntry *entries = DK_ENTRIES(result_mp->ma_keys);
117 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
119 for (Py_ssize_t i = 0; i < size; i++) {
120 PyDictKeyEntry *entry = &entries[i];
121 PyObject *value = entry->me_value;
124 PyObject *key = entry->me_key;
132 PyObject **key_ptr, **value_ptr;
135 bool is_unicode = DK_IS_UNICODE(result_mp->ma_keys);
138 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(result_mp->ma_keys);
140 key_ptr = &ep0->me_key;
141 value_ptr = &ep0->me_value;
142 entry_size =
sizeof(PyDictUnicodeEntry) /
sizeof(PyObject *);
144 PyDictKeyEntry *ep0 = DK_ENTRIES(result_mp->ma_keys);
146 key_ptr = &ep0->me_key;
147 value_ptr = &ep0->me_value;
148 entry_size =
sizeof(PyDictKeyEntry) /
sizeof(PyObject *);
151 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
153 for (Py_ssize_t i = 0; i < size; i++) {
154 PyObject *value = *value_ptr;
159 PyObject *key = *key_ptr;
163 value_ptr += entry_size;
164 key_ptr += entry_size;
168 Nuitka_Py_IncRefTotal(tstate);
169 Nuitka_GC_Track(result_mp);
173 result = _PyDict_NewPresized(dict_mp->ma_used);
175#if PYTHON_VERSION < 0x3b0
176 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
178 for (Py_ssize_t i = 0; i < size; i++) {
179 PyDictKeyEntry *entry = &DK_ENTRIES(dict_mp->ma_keys)[i];
180 PyObject *value = entry->me_value;
183 PyObject *key = entry->me_key;
188 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
194 PyObject *key, *value;
196 while (Nuitka_DictNext((PyObject *)dict_mp, &pos, &key, &value)) {
202 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
210 Py_END_CRITICAL_SECTION();
215PyObject *DEEP_COPY_DICT(PyThreadState *tstate, PyObject *dict_value) {
218#if _NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT
219 CHECK_OBJECT(dict_value);
220 assert(PyDict_CheckExact(dict_value));
222 result = DICT_COPY(tstate, dict_value);
225 PyObject *key, *value;
227 while (Nuitka_DictNext(dict_value, &pos, &key, &value)) {
228 PyObject *dict_value_copy = DEEP_COPY(tstate, value);
230 if (dict_value_copy != value) {
231 NUITKA_MAY_BE_UNUSED
bool res = DICT_SET_ITEM(result, key, dict_value_copy);
235 Py_DECREF(dict_value_copy);
238 Py_BEGIN_CRITICAL_SECTION(dict_value);
240 CHECK_OBJECT(dict_value);
241 assert(PyDict_CheckExact(dict_value));
243 if (((PyDictObject *)dict_value)->ma_used == 0) {
244 result = MAKE_DICT_EMPTY(tstate);
246 PyDictObject *dict_mp = (PyDictObject *)dict_value;
248#if PYTHON_VERSION < 0x300
251 result = _PyDict_NewPresized(dict_mp->ma_used);
253 for (Py_ssize_t i = 0; i <= dict_mp->ma_mask; i++) {
254 PyDictEntry *entry = &dict_mp->ma_table[i];
256 if (entry->me_value != NULL) {
257 PyObject *key = entry->me_key;
259 PyObject *value = entry->me_value;
260 value = DEEP_COPY(tstate, value);
262 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
270 if (_PyDict_HasSplitTable(dict_mp)) {
271 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
272 assert(result_mp != NULL);
273 result = (PyObject *)result_mp;
275#if PYTHON_VERSION < 0x3b0
276 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
278 Py_ssize_t size = dict_mp->ma_keys->dk_nentries + dict_mp->ma_keys->dk_usable;
281#if PYTHON_VERSION < 0x3d0
282 PyDictValues *new_values = _Nuitka_PyDict_new_values(size);
283 assert(new_values != NULL);
285#if PYTHON_VERSION >= 0x3b0
287 size_t prefix_size = ((uint8_t *)new_values)[-1];
288 memcpy((
char *)new_values - prefix_size, (
char *)dict_mp->ma_values - prefix_size, prefix_size - 1);
291 PyDictValues *new_values = _Nuitka_PyDict_copy_values(dict_mp->ma_values);
292 assert(new_values != NULL);
293 size = new_values->capacity;
296 result_mp->ma_values = new_values;
297 result_mp->ma_keys = dict_mp->ma_keys;
298 result_mp->ma_used = dict_mp->ma_used;
300 Nuitka_Py_IncRefTotal(tstate);
301 dict_mp->ma_keys->dk_refcnt += 1;
303 for (Py_ssize_t i = 0; i < size; i++) {
304 if (DK_VALUE(dict_mp, i)) {
305 PyObject *value = DK_VALUE(dict_mp, i);
306 value = DEEP_COPY(tstate, value);
308 DK_VALUE(result_mp, i) = value;
311 DK_VALUE(result_mp, i) = NULL;
315 Nuitka_GC_Track(result_mp);
317#if PYTHON_VERSION >= 0x360 && !defined(Py_GIL_DISABLED)
321 if (dict_mp->ma_values == NULL && IS_COMPACT(dict_mp)) {
322 assert(dict_mp->ma_values == NULL);
323 assert(dict_mp->ma_keys->dk_refcnt == 1);
325 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
326 result = (PyObject *)result_mp;
328 result_mp->ma_values = NULL;
329 result_mp->ma_used = dict_mp->ma_used;
331 Py_ssize_t keys_size = _Nuitka_Py_PyDict_KeysSize(dict_mp->ma_keys);
332 result_mp->ma_keys = _Nuitka_AllocatePyDictKeysObject(tstate, keys_size);
333 assert(result_mp->ma_keys);
335 memcpy(result_mp->ma_keys, dict_mp->ma_keys, keys_size);
338#if PYTHON_VERSION < 0x3b0
339 PyDictKeyEntry *entries = DK_ENTRIES(result_mp->ma_keys);
340 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
342 for (Py_ssize_t i = 0; i < size; i++) {
343 PyDictKeyEntry *entry = &entries[i];
344 PyObject *value = entry->me_value;
347 PyObject *key = entry->me_key;
351 value = DEEP_COPY(tstate, value);
353 entry->me_value = value;
357 PyObject **key_ptr, **value_ptr;
360 bool is_unicode = DK_IS_UNICODE(result_mp->ma_keys);
363 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(result_mp->ma_keys);
365 key_ptr = &ep0->me_key;
366 value_ptr = &ep0->me_value;
367 entry_size =
sizeof(PyDictUnicodeEntry) /
sizeof(PyObject *);
369 PyDictKeyEntry *ep0 = DK_ENTRIES(result_mp->ma_keys);
371 key_ptr = &ep0->me_key;
372 value_ptr = &ep0->me_value;
373 entry_size =
sizeof(PyDictKeyEntry) /
sizeof(PyObject *);
376 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
378 for (Py_ssize_t i = 0; i < size; i++) {
379 PyObject *value = *value_ptr;
382 value = DEEP_COPY(tstate, value);
384 PyObject *key = *key_ptr;
388 value_ptr += entry_size;
389 key_ptr += entry_size;
393 Nuitka_Py_IncRefTotal(tstate);
394 Nuitka_GC_Track(result_mp);
398 result = _PyDict_NewPresized(dict_mp->ma_used);
400#if PYTHON_VERSION < 0x3b0
401 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
403 for (Py_ssize_t i = 0; i < size; i++) {
404 PyDictKeyEntry *entry = &DK_ENTRIES(dict_mp->ma_keys)[i];
405 PyObject *value = entry->me_value;
408 PyObject *key = entry->me_key;
413 value = DEEP_COPY(tstate, value);
415 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
423 PyObject *key, *value;
425 while (Nuitka_DictNext((PyObject *)dict_mp, &pos, &key, &value)) {
431 value = DEEP_COPY(tstate, value);
433 NUITKA_MAY_BE_UNUSED
int res = PyDict_SetItem(result, key, value);
443 Py_END_CRITICAL_SECTION();