Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersDictionariesGenerated.c
1// Copyright 2026, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* This file is included from another C file, help IDEs to still parse it on its own. */
4#ifdef __IDE_ONLY__
5#include "nuitka/prelude.h"
6#endif
7
8/* WARNING, this code is GENERATED. Modify the template HelperDictionaryCopy.c.j2 instead! */
9
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));
14
15 return PyDict_Copy(dict_value);
16#else
17 PyObject *result;
18 Py_BEGIN_CRITICAL_SECTION(dict_value);
19
20 CHECK_OBJECT(dict_value);
21 assert(PyDict_CheckExact(dict_value));
22
23 if (((PyDictObject *)dict_value)->ma_used == 0) {
24 result = MAKE_DICT_EMPTY(tstate);
25 } else {
26 PyDictObject *dict_mp = (PyDictObject *)dict_value;
27
28#if PYTHON_VERSION < 0x300
29 // For Python3, this can be done much faster in the same way as it is
30 // done in parameter parsing.
31 result = _PyDict_NewPresized(dict_mp->ma_used);
32
33 for (Py_ssize_t i = 0; i <= dict_mp->ma_mask; i++) {
34 PyDictEntry *entry = &dict_mp->ma_table[i];
35
36 if (entry->me_value != NULL) {
37 PyObject *key = entry->me_key;
38
39 PyObject *value = entry->me_value;
40
41 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
42 assert(res == 0);
43 }
44 }
45#else
46 /* Python 3 */
47 if (_PyDict_HasSplitTable(dict_mp)) {
48 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
49 assert(result_mp != NULL);
50 result = (PyObject *)result_mp;
51
52#if PYTHON_VERSION < 0x3b0
53 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
54#else
55 Py_ssize_t size = dict_mp->ma_keys->dk_nentries + dict_mp->ma_keys->dk_usable;
56#endif
57
58#if PYTHON_VERSION < 0x3d0
59 PyDictValues *new_values = _Nuitka_PyDict_new_values(size);
60 assert(new_values != NULL);
61
62#if PYTHON_VERSION >= 0x3b0
63 // Need to preserve values prefix.
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);
66#endif
67#else
68 PyDictValues *new_values = _Nuitka_PyDict_copy_values(dict_mp->ma_values);
69 assert(new_values != NULL);
70 size = new_values->capacity;
71#endif
72
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;
76
77 Nuitka_Py_IncRefTotal(tstate);
78 dict_mp->ma_keys->dk_refcnt += 1;
79
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);
83
84 DK_VALUE(result_mp, i) = value;
85 Py_INCREF(value);
86
87 } else {
88 DK_VALUE(result_mp, i) = NULL;
89 }
90 }
91
92 Nuitka_GC_Track(result_mp);
93 } else
94#if PYTHON_VERSION >= 0x360 && !defined(Py_GIL_DISABLED)
95 // Fast dictionary copy if it has at least 2/3 space usage. This is most relevant
96 // for the DICT_COPY, where it might even be the intention to trigger a shrink with
97 // a fresh copy.
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);
101
102 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
103 result = (PyObject *)result_mp;
104
105 result_mp->ma_values = NULL;
106 result_mp->ma_used = dict_mp->ma_used;
107
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);
111
112 memcpy(result_mp->ma_keys, dict_mp->ma_keys, keys_size);
113
114 // Take reference of all keys and values.
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);
118
119 for (Py_ssize_t i = 0; i < size; i++) {
120 PyDictKeyEntry *entry = &entries[i];
121 PyObject *value = entry->me_value;
122
123 if (value != NULL) {
124 PyObject *key = entry->me_key;
125
126 Py_INCREF(key);
127
128 Py_INCREF(value);
129 }
130 }
131#else
132 PyObject **key_ptr, **value_ptr;
133 size_t entry_size;
134
135 bool is_unicode = DK_IS_UNICODE(result_mp->ma_keys);
136
137 if (is_unicode) {
138 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(result_mp->ma_keys);
139
140 key_ptr = &ep0->me_key;
141 value_ptr = &ep0->me_value;
142 entry_size = sizeof(PyDictUnicodeEntry) / sizeof(PyObject *);
143 } else {
144 PyDictKeyEntry *ep0 = DK_ENTRIES(result_mp->ma_keys);
145
146 key_ptr = &ep0->me_key;
147 value_ptr = &ep0->me_value;
148 entry_size = sizeof(PyDictKeyEntry) / sizeof(PyObject *);
149 }
150
151 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
152
153 for (Py_ssize_t i = 0; i < size; i++) {
154 PyObject *value = *value_ptr;
155
156 if (value != NULL) {
157
158 Py_INCREF(value);
159 PyObject *key = *key_ptr;
160 Py_INCREF(key);
161 }
162
163 value_ptr += entry_size;
164 key_ptr += entry_size;
165 }
166#endif
167
168 Nuitka_Py_IncRefTotal(tstate);
169 Nuitka_GC_Track(result_mp);
170 } else
171#endif
172 {
173 result = _PyDict_NewPresized(dict_mp->ma_used);
174
175#if PYTHON_VERSION < 0x3b0
176 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
177
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;
181
182 if (value != NULL) {
183 PyObject *key = entry->me_key;
184 CHECK_OBJECT(key);
185
186 CHECK_OBJECT(value);
187
188 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
189 assert(res == 0);
190 }
191 }
192#else
193 Py_ssize_t pos = 0;
194 PyObject *key, *value;
195
196 while (Nuitka_DictNext((PyObject *)dict_mp, &pos, &key, &value)) {
197 CHECK_OBJECT(key);
198 CHECK_OBJECT(value);
199
200 CHECK_OBJECT(value);
201
202 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
203 assert(res == 0);
204 }
205#endif
206 }
207#endif
208 }
209
210 Py_END_CRITICAL_SECTION();
211 return result;
212#endif
213}
214
215PyObject *DEEP_COPY_DICT(PyThreadState *tstate, PyObject *dict_value) {
216 PyObject *result;
217
218#if _NUITKA_EXPERIMENTAL_DISABLE_DICT_OPT
219 CHECK_OBJECT(dict_value);
220 assert(PyDict_CheckExact(dict_value));
221
222 result = DICT_COPY(tstate, dict_value);
223
224 Py_ssize_t pos = 0;
225 PyObject *key, *value;
226
227 while (Nuitka_DictNext(dict_value, &pos, &key, &value)) {
228 PyObject *dict_value_copy = DEEP_COPY(tstate, value);
229
230 if (dict_value_copy != value) {
231 NUITKA_MAY_BE_UNUSED bool res = DICT_SET_ITEM(result, key, dict_value_copy);
232 assert(res);
233 }
234
235 Py_DECREF(dict_value_copy);
236 }
237#else
238 Py_BEGIN_CRITICAL_SECTION(dict_value);
239
240 CHECK_OBJECT(dict_value);
241 assert(PyDict_CheckExact(dict_value));
242
243 if (((PyDictObject *)dict_value)->ma_used == 0) {
244 result = MAKE_DICT_EMPTY(tstate);
245 } else {
246 PyDictObject *dict_mp = (PyDictObject *)dict_value;
247
248#if PYTHON_VERSION < 0x300
249 // For Python3, this can be done much faster in the same way as it is
250 // done in parameter parsing.
251 result = _PyDict_NewPresized(dict_mp->ma_used);
252
253 for (Py_ssize_t i = 0; i <= dict_mp->ma_mask; i++) {
254 PyDictEntry *entry = &dict_mp->ma_table[i];
255
256 if (entry->me_value != NULL) {
257 PyObject *key = entry->me_key;
258
259 PyObject *value = entry->me_value;
260 value = DEEP_COPY(tstate, value);
261
262 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
263 assert(res == 0);
264
265 Py_DECREF(value);
266 }
267 }
268#else
269 /* Python 3 */
270 if (_PyDict_HasSplitTable(dict_mp)) {
271 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
272 assert(result_mp != NULL);
273 result = (PyObject *)result_mp;
274
275#if PYTHON_VERSION < 0x3b0
276 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
277#else
278 Py_ssize_t size = dict_mp->ma_keys->dk_nentries + dict_mp->ma_keys->dk_usable;
279#endif
280
281#if PYTHON_VERSION < 0x3d0
282 PyDictValues *new_values = _Nuitka_PyDict_new_values(size);
283 assert(new_values != NULL);
284
285#if PYTHON_VERSION >= 0x3b0
286 // Need to preserve values prefix.
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);
289#endif
290#else
291 PyDictValues *new_values = _Nuitka_PyDict_copy_values(dict_mp->ma_values);
292 assert(new_values != NULL);
293 size = new_values->capacity;
294#endif
295
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;
299
300 Nuitka_Py_IncRefTotal(tstate);
301 dict_mp->ma_keys->dk_refcnt += 1;
302
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);
307
308 DK_VALUE(result_mp, i) = value;
309
310 } else {
311 DK_VALUE(result_mp, i) = NULL;
312 }
313 }
314
315 Nuitka_GC_Track(result_mp);
316 } else
317#if PYTHON_VERSION >= 0x360 && !defined(Py_GIL_DISABLED)
318 // Fast dictionary copy if it has at least 2/3 space usage. This is most relevant
319 // for the DICT_COPY, where it might even be the intention to trigger a shrink with
320 // a fresh copy.
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);
324
325 PyDictObject *result_mp = _Nuitka_AllocatePyDictObject(tstate);
326 result = (PyObject *)result_mp;
327
328 result_mp->ma_values = NULL;
329 result_mp->ma_used = dict_mp->ma_used;
330
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);
334
335 memcpy(result_mp->ma_keys, dict_mp->ma_keys, keys_size);
336
337 // Take reference of all keys and values.
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);
341
342 for (Py_ssize_t i = 0; i < size; i++) {
343 PyDictKeyEntry *entry = &entries[i];
344 PyObject *value = entry->me_value;
345
346 if (value != NULL) {
347 PyObject *key = entry->me_key;
348
349 Py_INCREF(key);
350
351 value = DEEP_COPY(tstate, value);
352
353 entry->me_value = value;
354 }
355 }
356#else
357 PyObject **key_ptr, **value_ptr;
358 size_t entry_size;
359
360 bool is_unicode = DK_IS_UNICODE(result_mp->ma_keys);
361
362 if (is_unicode) {
363 PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(result_mp->ma_keys);
364
365 key_ptr = &ep0->me_key;
366 value_ptr = &ep0->me_value;
367 entry_size = sizeof(PyDictUnicodeEntry) / sizeof(PyObject *);
368 } else {
369 PyDictKeyEntry *ep0 = DK_ENTRIES(result_mp->ma_keys);
370
371 key_ptr = &ep0->me_key;
372 value_ptr = &ep0->me_value;
373 entry_size = sizeof(PyDictKeyEntry) / sizeof(PyObject *);
374 }
375
376 Py_ssize_t size = DK_ENTRIES_SIZE(result_mp->ma_keys);
377
378 for (Py_ssize_t i = 0; i < size; i++) {
379 PyObject *value = *value_ptr;
380
381 if (value != NULL) {
382 value = DEEP_COPY(tstate, value);
383 *value_ptr = value;
384 PyObject *key = *key_ptr;
385 Py_INCREF(key);
386 }
387
388 value_ptr += entry_size;
389 key_ptr += entry_size;
390 }
391#endif
392
393 Nuitka_Py_IncRefTotal(tstate);
394 Nuitka_GC_Track(result_mp);
395 } else
396#endif
397 {
398 result = _PyDict_NewPresized(dict_mp->ma_used);
399
400#if PYTHON_VERSION < 0x3b0
401 Py_ssize_t size = DK_ENTRIES_SIZE(dict_mp->ma_keys);
402
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;
406
407 if (value != NULL) {
408 PyObject *key = entry->me_key;
409 CHECK_OBJECT(key);
410
411 CHECK_OBJECT(value);
412
413 value = DEEP_COPY(tstate, value);
414
415 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
416 assert(res == 0);
417
418 Py_DECREF(value);
419 }
420 }
421#else
422 Py_ssize_t pos = 0;
423 PyObject *key, *value;
424
425 while (Nuitka_DictNext((PyObject *)dict_mp, &pos, &key, &value)) {
426 CHECK_OBJECT(key);
427 CHECK_OBJECT(value);
428
429 CHECK_OBJECT(value);
430
431 value = DEEP_COPY(tstate, value);
432
433 NUITKA_MAY_BE_UNUSED int res = PyDict_SetItem(result, key, value);
434 assert(res == 0);
435
436 Py_DECREF(value);
437 }
438#endif
439 }
440#endif
441 }
442
443 Py_END_CRITICAL_SECTION();
444#endif
445
446 return result;
447}
448
449// Part of "Nuitka", an optimizing Python compiler that is compatible and
450// integrates with CPython, but also works on its own.
451//
452// Licensed under the GNU Affero General Public License, Version 3 (the "License");
453// you may not use this file except in compliance with the License.
454// You may obtain a copy of the License at
455//
456// http://www.gnu.org/licenses/agpl.txt
457//
458// Unless required by applicable law or agreed to in writing, software
459// distributed under the License is distributed on an "AS IS" BASIS,
460// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
461// See the License for the specific language governing permissions and
462// limitations under the License.