Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersLists.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* This helpers is used to work with lists.
4
5*/
6
7// This file is included from another C file, help IDEs to still parse it on
8// its own.
9#ifdef __IDE_ONLY__
10#include "nuitka/prelude.h"
11#endif
12
13// #include "richcomparisons.h"
14
15static PyObject *Nuitka_LongFromCLong(long ival);
16
17#ifdef Py_GIL_DISABLED
18typedef struct {
19 Py_ssize_t allocated;
20 PyObject *ob_item[];
21} _PyListArray;
22
23static _PyListArray *Nuitka_AllocateListArray(size_t capacity) {
24 if (unlikely(capacity > PY_SSIZE_T_MAX / sizeof(PyObject *) - 1)) {
25 return NULL;
26 }
27
28 // TODO: API call to be removed.
29 _PyListArray *list_array = PyMem_Malloc(sizeof(_PyListArray) + capacity * sizeof(PyObject *));
30
31 if (unlikely(list_array == NULL)) {
32 return NULL;
33 }
34
35 list_array->allocated = capacity;
36 return list_array;
37}
38
39// spell-checker: ignore use_qsbr
40static void Nuitka_FreeListArray(PyObject **items, bool use_qsbr) {
41 _PyListArray *array = _Py_CONTAINER_OF(items, _PyListArray, ob_item);
42
43 if (use_qsbr) {
44 NuitkaMem_FreeDelayed(array);
45 } else {
46 NuitkaMem_Free(array);
47 }
48}
49
50#endif
51
52#if NUITKA_LIST_HAS_FREELIST
53
54PyObject *MAKE_LIST_EMPTY(PyThreadState *tstate, Py_ssize_t size) {
55 assert(size >= 0);
56
57#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
58 return PyList_New(size);
59#else
60#if PYTHON_VERSION >= 0x3e0
61 PyListObject *result_list = (PyListObject *)Nuitka_PyFreeList_Pop(&_Py_freelists_GET()->lists);
62
63 if (result_list == NULL) {
64 result_list = (PyListObject *)Nuitka_GC_New(&PyList_Type);
65 } else {
66 Nuitka_Py_NewReference((PyObject *)result_list);
67 }
68#else
69 // This is the CPython name, spell-checker: ignore numfree
70#if PYTHON_VERSION < 0x3d0
71 PyListObject **items = tstate->interp->list.free_list;
72 int *numfree = &tstate->interp->list.numfree;
73#else
74 struct _Py_object_freelists *freelists = _Nuitka_object_freelists_GET(tstate);
75 struct _Py_list_freelist *state = &freelists->lists;
76 PyListObject **items = state->items;
77 int *numfree = &state->numfree;
78#endif
79 assert(*numfree >= 0);
80 PyListObject *result_list;
81
82 if (*numfree) {
83 (*numfree) -= 1;
84 result_list = items[*numfree];
85
86 Nuitka_Py_NewReference((PyObject *)result_list);
87 } else {
88 result_list = (PyListObject *)Nuitka_GC_New(&PyList_Type);
89 }
90#endif
91 assert(result_list != NULL);
92 assert(PyList_CheckExact(result_list));
93
94 // Elements are allocated separately.
95 if (size > 0) {
96#ifdef Py_GIL_DISABLED
97 _PyListArray *list_array = Nuitka_AllocateListArray(size);
98
99 if (unlikely(list_array == NULL)) {
100 Py_DECREF(result_list);
101 return PyErr_NoMemory();
102 }
103#else
104 result_list->ob_item = (PyObject **)NuitkaMem_Calloc(size, sizeof(PyObject *));
105
106 if (unlikely(result_list->ob_item == NULL)) {
107 Py_DECREF(result_list);
108 return PyErr_NoMemory();
109 }
110#endif
111 } else {
112 result_list->ob_item = NULL;
113 }
114
115 Py_SET_SIZE(result_list, size);
116 result_list->allocated = size;
117
118 Nuitka_GC_Track(result_list);
119
120 return (PyObject *)result_list;
121#endif
122}
123#endif
124
125PyObject *LIST_COPY(PyThreadState *tstate, PyObject *list) {
126 CHECK_OBJECT(list);
127 assert(PyList_CheckExact(list));
128
129 Py_ssize_t size = PyList_GET_SIZE(list);
130 PyObject *result = MAKE_LIST_EMPTY(tstate, size);
131
132 if (unlikely(result == NULL)) {
133 return NULL;
134 }
135
136 for (Py_ssize_t i = 0; i < size; i++) {
137 PyObject *item = PyList_GET_ITEM(list, i);
138 Py_INCREF(item);
139 PyList_SET_ITEM(result, i, item);
140 }
141
142 return result;
143}
144
145static bool LIST_RESIZE(PyListObject *list, Py_ssize_t new_size) {
146 CHECK_OBJECT(list);
147 assert(new_size >= 0);
148
149 Py_ssize_t allocated = list->allocated;
150
151 if (allocated >= new_size && new_size >= (allocated >> 1)) {
152 Py_SET_SIZE(list, new_size);
153
154 return true;
155 }
156
157 size_t new_allocated;
158
159 if (new_size == 0) {
160 new_allocated = 0;
161 } else {
162 new_allocated = ((size_t)new_size + (new_size >> 3) + 6) & ~(size_t)3;
163 assert(new_allocated >= (size_t)new_size);
164 }
165
166#ifdef Py_GIL_DISABLED
167 _PyListArray *array = Nuitka_AllocateListArray(new_allocated);
168
169 if (array == NULL) {
170 PyErr_NoMemory();
171 return -1;
172 }
173 PyObject **old_items = list->ob_item;
174 if (list->ob_item != NULL) {
175 size_t num_allocated_bytes;
176 if (new_allocated < (size_t)allocated) {
177 num_allocated_bytes = new_allocated * sizeof(PyObject *);
178 } else {
179 num_allocated_bytes = allocated * sizeof(PyObject *);
180 }
181 memcpy(array->ob_item, list->ob_item, num_allocated_bytes);
182 }
183 if (new_allocated > (size_t)allocated) {
184 memset(array->ob_item + allocated, 0, sizeof(PyObject *) * (new_allocated - allocated));
185 }
186 _Py_atomic_store_ptr_release(&list->ob_item, &array->ob_item);
187 list->allocated = new_allocated;
188 Py_SET_SIZE(list, new_size);
189 if (old_items != NULL) {
190 Nuitka_FreeListArray(old_items, _PyObject_GC_IS_SHARED(list));
191 }
192#else
193 size_t num_allocated_bytes = new_allocated * sizeof(PyObject *);
194
195 // TODO: For Python3.13 No-GIL this is different code
196 PyObject **items = (PyObject **)NuitkaMem_Realloc(list->ob_item, num_allocated_bytes);
197 if (unlikely(items == NULL)) {
198 PyErr_NoMemory();
199 return false;
200 }
201
202 list->ob_item = items;
203 Py_SET_SIZE(list, new_size);
204 list->allocated = new_allocated;
205#endif
206
207 return true;
208}
209
210bool LIST_EXTEND_FROM_LIST(PyObject *list, PyObject *other) {
211#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
212 PyObject *result = _PyList_Extend((PyListObject *)list, other);
213 if (result != NULL) {
214 Py_DECREF(result);
215 return true;
216 } else {
217 return false;
218 }
219#else
220 assert(PyList_CheckExact(list));
221 assert(PyList_CheckExact(other));
222
223 size_t n = PyList_GET_SIZE(other);
224
225 if (n == 0) {
226 return true;
227 }
228
229 size_t m = Py_SIZE(list);
230
231 if (LIST_RESIZE((PyListObject *)list, m + n) == false) {
232 return false;
233 }
234
235 PyObject **src = &PyList_GET_ITEM(other, 0);
236 PyObject **dest = &PyList_GET_ITEM(list, m);
237
238 for (size_t i = 0; i < n; i++) {
239 PyObject *o = src[i];
240 Py_INCREF(o);
241
242 dest[i] = o;
243 }
244
245 return true;
246#endif
247}
248
249bool LIST_EXTEND_FROM_ITERABLE(PyThreadState *tstate, PyObject *target, PyObject *other) {
250 CHECK_OBJECT(target);
251 assert(PyList_CheckExact(target));
252
253 CHECK_OBJECT(other);
254
255 PyListObject *list = (PyListObject *)target;
256
257#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
258 PyObject *result = _PyList_Extend(list, other);
259 if (result != NULL) {
260 Py_DECREF(result);
261 return true;
262 } else {
263 return false;
264 }
265#else
266 // First attempt those things that occur most often. Keep in mind that
267 // other might be the same object as list.
268 PyObject **src;
269 Py_ssize_t src_size;
270
271 if (PyList_CheckExact(other)) { // this covers list == other too.
272 src = _PyList_ITEMS(other);
273 src_size = PyList_GET_SIZE(other);
274 } else if (PyTuple_CheckExact(other)) {
275 src = _PyTuple_ITEMS(other);
276 src_size = PyTuple_GET_SIZE(other);
277 } else {
278 src = NULL;
279#ifndef __NUITKA_NO_ASSERT__
280 src_size = 0;
281#endif
282 }
283
284 if (src != NULL) {
285 if (src_size == 0) {
286 return true;
287 }
288
289 Py_ssize_t list_size = PyList_GET_SIZE(list);
290
291 // Overflow is not really realistic, so we only assert against it.
292 assert(list_size <= PY_SSIZE_T_MAX - src_size);
293 if (LIST_RESIZE(list, list_size + src_size) == false) {
294 return false;
295 }
296
297 PyObject **target_items = _PyList_ITEMS(list) + list_size;
298
299 for (Py_ssize_t i = 0; i < src_size; i++) {
300 PyObject *value = src[i];
301 Py_INCREF(value);
302 *target_items++ = value;
303 }
304
305 return true;
306 }
307
308 // Slow path needs to use iterator. TODO:
309 PyObject *iter = MAKE_ITERATOR(tstate, other);
310
311 if (iter == NULL) {
312 return false;
313 }
314 PyObject *(*iternext)(PyObject *) = *Py_TYPE(iter)->tp_iternext;
315
316 Py_ssize_t cur_size = PyList_GET_SIZE(list);
317
318#if PYTHON_VERSION >= 0x300
319 // Guess a iterator size if possible
320 src_size = PyObject_LengthHint(other, 8);
321
322 if (src_size < 0) {
323 Py_DECREF(iter);
324 return false;
325 }
326
327 Py_ssize_t list_size = PyList_GET_SIZE(list);
328
329 if (list_size > PY_SSIZE_T_MAX - src_size) {
330 // Overflow is not really realistic, hope is, it will not come true.
331 } else {
332 // Allocate the space in one go.
333 if (LIST_RESIZE(list, list_size + src_size) == false) {
334 Py_DECREF(iter);
335 return false;
336 }
337
338 // Restore validity of the object for the time being.
339 Py_SET_SIZE(list, list_size);
340 }
341#endif
342
343 for (;;) {
344 PyObject *item = iternext(iter);
345
346 if (item == NULL) {
347 bool stop_iteration_error = CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(tstate);
348
349 Py_DECREF(iter);
350
351 if (unlikely(stop_iteration_error == false)) {
352 if (cur_size < list->allocated) {
353 if (LIST_RESIZE(list, cur_size) == false) {
354 return false;
355 }
356 }
357
358 return false;
359 }
360
361 break;
362 }
363
364 CHECK_OBJECT(item);
365
366 if (cur_size < list->allocated) {
367 // Already allocated, so we can just set it.
368 PyList_SET_ITEM(list, cur_size, item);
369 Py_SET_SIZE(list, cur_size + 1);
370 } else {
371 assert(cur_size != PY_SSIZE_T_MAX);
372
373 if (LIST_RESIZE(list, cur_size + 1) == false) {
374 return false;
375 }
376
377 PyList_SET_ITEM(list, cur_size, item);
378 }
379 cur_size += 1;
380 }
381
382 /* Cut back result list if initial guess was too large. */
383 assert(cur_size == PyList_GET_SIZE(list));
384
385 if (cur_size < list->allocated) {
386 if (LIST_RESIZE(list, cur_size) == false) {
387 return false;
388 }
389 }
390
391 return true;
392#endif
393}
394
395#if PYTHON_VERSION >= 0x390
396bool LIST_EXTEND_FOR_UNPACK(PyThreadState *tstate, PyObject *list, PyObject *other) {
397 // TODO: For improved performance, inline this, but we probably wait
398 // until code generation for this kind of helpers is there.
399 bool result = LIST_EXTEND_FROM_ITERABLE(tstate, list, other);
400
401 if (likely(result)) {
402 return true;
403 }
404
405 PyObject *error = GET_ERROR_OCCURRED(tstate);
406
407 assert(error != NULL);
408
409 if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, error, PyExc_TypeError) &&
410 (Py_TYPE(other)->tp_iter == NULL && !PySequence_Check(other))) {
411 CLEAR_ERROR_OCCURRED(tstate);
412 PyErr_Format(PyExc_TypeError, "Value after * must be an iterable, not %s", Py_TYPE(other)->tp_name);
413 }
414
415 return false;
416}
417#endif
418
419bool LIST_APPEND1(PyObject *target, PyObject *item) {
420 CHECK_OBJECT(target);
421 assert(PyList_CheckExact(target));
422
423 CHECK_OBJECT(item);
424
425#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
426 int res = PyList_Append(target, item);
427 Py_DECREF(item);
428 return res == 0;
429#else
430 PyListObject *list = (PyListObject *)target;
431
432 Py_ssize_t cur_size = PyList_GET_SIZE(list);
433
434 // Overflow is not really realistic, so we only assert against it.
435 assert(cur_size <= PY_SSIZE_T_MAX);
436
437 if (LIST_RESIZE(list, cur_size + 1) == false) {
438 return false;
439 }
440
441 PyList_SET_ITEM(list, cur_size, item);
442
443 return true;
444#endif
445}
446
447bool LIST_APPEND0(PyObject *target, PyObject *item) {
448 CHECK_OBJECT(target);
449 assert(PyList_CheckExact(target));
450
451 CHECK_OBJECT(item);
452
453#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
454 int res = PyList_Append(target, item);
455 return res == 0;
456#else
457 PyListObject *list = (PyListObject *)target;
458
459 Py_ssize_t cur_size = PyList_GET_SIZE(list);
460
461 // Overflow is not really realistic, so we only assert against it.
462 assert(cur_size <= PY_SSIZE_T_MAX);
463
464 if (LIST_RESIZE(list, cur_size + 1) == false) {
465 return false;
466 }
467
468 PyList_SET_ITEM0(list, cur_size, item);
469
470 return true;
471#endif
472}
473
474bool LIST_REMOVE(PyObject *target, PyObject *item) {
475 CHECK_OBJECT(target);
476 assert(PyList_CheckExact(target));
477
478 CHECK_OBJECT(item);
479
480#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT && 0
481 // TODO: This is not exposed, would need to delete as slice instead.
482 int res = PyList_Remove(target, item);
483 return res == 0;
484#else
485 PyListObject *list = (PyListObject *)target;
486
487 Py_ssize_t cur_size = PyList_GET_SIZE(list);
488
489 for (Py_ssize_t i = 0; i < cur_size; i++) {
490 PyObject *element = list->ob_item[i];
491
492 Py_INCREF(element);
493 nuitka_bool cmp = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
494 Py_DECREF(element);
495
496 if (cmp == NUITKA_BOOL_TRUE) {
497 Py_DECREF(element);
498 Py_SET_SIZE(list, cur_size - 1);
499
500 memmove(list->ob_item + i, list->ob_item + i + 1, sizeof(PyObject *) * (cur_size - i - 1));
501
502 return true;
503 } else if (unlikely(cmp == NUITKA_BOOL_EXCEPTION)) {
504 return false;
505 }
506 }
507
508 PyThreadState *tstate = PyThreadState_GET();
509
510 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ValueError, "list.remove(x): x not in list");
511 return false;
512#endif
513}
514
515void LIST_CLEAR(PyObject *target) {
516 CHECK_OBJECT(target);
517 assert(PyList_CheckExact(target));
518
519 PyListObject *list = (PyListObject *)target;
520
521 PyObject **items = list->ob_item;
522
523 if (items != NULL) {
524 // Make the list empty first, so the data we release is not accessible.
525 Py_ssize_t i = Py_SIZE(list);
526 Py_SET_SIZE(list, 0);
527 list->ob_item = NULL;
528 list->allocated = 0;
529
530 while (--i >= 0) {
531 Py_XDECREF(items[i]);
532 }
533
534 PyMem_Free(items);
535 }
536}
537
538PyObject *getListIndexObject(Py_ssize_t value) {
539#if PYTHON_VERSION < 0x300
540 return PyInt_FromSsize_t(value);
541#else
542 // TODO: Actually to be fully correct, we will need a "Nuitka_LongFromCSsize_t" which
543 // we do not have yet.
544 return Nuitka_LongFromCLong((long)value);
545#endif
546}
547
548PyObject *LIST_COUNT(PyObject *list, PyObject *item) {
549 CHECK_OBJECT(list);
550 assert(PyList_CheckExact(list));
551
552 Py_ssize_t count = 0;
553
554 for (Py_ssize_t i = 0; i < Py_SIZE(list); i++) {
555 PyObject *element = PyList_GET_ITEM(list, i);
556
557 // Fast path, is identical
558 if (element == item) {
559 count++;
560 continue;
561 }
562
563 // Rich compare element while holding a reference. TODO: If we knew the type
564 // of "item" we could be faster by picking variants that know stuff, but
565 // maybe it is not as important.
566 Py_INCREF(element);
567 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
568 Py_DECREF(element);
569
570 if (nbool_res == NUITKA_BOOL_TRUE) {
571 count++;
572 continue;
573 }
574
575 // Pass on exceptions from comparisons.
576 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
577 return NULL;
578 }
579 }
580
581 return getListIndexObject(count);
582}
583
584static PyObject *_LIST_INDEX_COMMON(PyThreadState *tstate, PyListObject *list, PyObject *item, Py_ssize_t start,
585 Py_ssize_t stop) {
586 // Negative values for start/stop are handled here.
587 if (start < 0) {
588 start += Py_SIZE(list);
589
590 if (start < 0) {
591 start = 0;
592 }
593 }
594
595 if (stop < 0) {
596 stop += Py_SIZE(list);
597
598 if (stop < 0) {
599 stop = 0;
600 }
601 }
602
603 for (Py_ssize_t i = start; i < stop && i < Py_SIZE(list); i++) {
604 PyObject *element = list->ob_item[i];
605
606 Py_INCREF(element);
607 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(element, item);
608 Py_DECREF(element);
609
610 if (nbool_res == NUITKA_BOOL_TRUE) {
611 return getListIndexObject(i);
612 }
613
614 // Pass on exceptions from comparisons.
615 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
616 return NULL;
617 }
618 }
619
620#if PYTHON_VERSION < 0x300
621 PyObject *err_format = PyString_FromString("%r is not in list");
622 PyObject *format_tuple = MAKE_TUPLE1_0(tstate, item);
623 PyObject *err_string = PyString_Format(err_format, format_tuple);
624 Py_DECREF(format_tuple);
625
626 if (err_string == NULL) {
627 return NULL;
628 }
629
630 SET_CURRENT_EXCEPTION_TYPE0_VALUE1(tstate, PyExc_ValueError, err_string);
631 return NULL;
632#else
633 PyErr_Format(PyExc_ValueError, "%R is not in list", item);
634 return NULL;
635#endif
636}
637
638PyObject *LIST_INDEX2(PyThreadState *tstate, PyObject *list, PyObject *item) {
639 CHECK_OBJECT(list);
640 assert(PyList_CheckExact(list));
641
642 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, 0, Py_SIZE(list));
643}
644
645PyObject *LIST_INDEX3(PyThreadState *tstate, PyObject *list, PyObject *item, PyObject *start) {
646 CHECK_OBJECT(list);
647 assert(PyList_CheckExact(list));
648
649 PyObject *start_index = Nuitka_Number_IndexAsLong(start);
650
651 if (unlikely(start_index == NULL)) {
652 // TODO: Clearing should be useless here.
653 CLEAR_ERROR_OCCURRED(tstate);
654
655 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
656 "slice indices must be integers or have an __index__ method");
657 return NULL;
658 }
659
660 Py_ssize_t start_ssize;
661#if PYTHON_VERSION < 0x300
662 if (PyInt_CheckExact(start_index)) {
663 start_ssize = PyInt_AS_LONG(start_index);
664 } else {
665 start_ssize = PyLong_AsSsize_t(start_index);
666 }
667#else
668 start_ssize = PyLong_AsSsize_t(start_index);
669#endif
670
671 Py_DECREF(start_index);
672
673 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, start_ssize, Py_SIZE(list));
674}
675
676PyObject *LIST_INDEX4(PyThreadState *tstate, PyObject *list, PyObject *item, PyObject *start, PyObject *stop) {
677 CHECK_OBJECT(list);
678 assert(PyList_CheckExact(list));
679
680 PyObject *start_index = Nuitka_Number_IndexAsLong(start);
681
682 if (unlikely(start_index == NULL)) {
683 CLEAR_ERROR_OCCURRED(tstate);
684
685 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
686 "slice indices must be integers or have an __index__ method");
687 return NULL;
688 }
689
690 Py_ssize_t start_ssize;
691#if PYTHON_VERSION < 0x300
692 if (PyInt_CheckExact(start_index)) {
693 start_ssize = PyInt_AS_LONG(start_index);
694 } else {
695 start_ssize = PyLong_AsSsize_t(start_index);
696 }
697#else
698 start_ssize = PyLong_AsSsize_t(start_index);
699#endif
700
701 Py_DECREF(start_index);
702
703 PyObject *stop_index = Nuitka_Number_IndexAsLong(stop);
704
705 if (unlikely(stop_index == NULL)) {
706 Py_DECREF(start_index);
707
708 CLEAR_ERROR_OCCURRED(tstate);
709
710 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
711 "slice indices must be integers or have an __index__ method");
712 return NULL;
713 }
714
715 Py_ssize_t stop_ssize;
716#if PYTHON_VERSION < 0x300
717 if (PyInt_CheckExact(stop_index)) {
718 stop_ssize = PyInt_AS_LONG(stop_index);
719 } else {
720 stop_ssize = PyLong_AsSsize_t(stop_index);
721 }
722#else
723 stop_ssize = PyLong_AsSsize_t(stop_index);
724#endif
725
726 Py_DECREF(stop_index);
727
728 return _LIST_INDEX_COMMON(tstate, (PyListObject *)list, item, start_ssize, stop_ssize);
729}
730
731bool LIST_INSERT(PyThreadState *tstate, PyObject *list, PyObject *index, PyObject *item) {
732 CHECK_OBJECT(list);
733 assert(PyList_CheckExact(list));
734 CHECK_OBJECT(index);
735 CHECK_OBJECT(item);
736
737 // TODO: Avoid the clear, by having this as a variant that doesn't set the
738 // exception to begin with
739 PyObject *index_long = Nuitka_Number_IndexAsLong(index);
740
741 if (unlikely(index_long == NULL)) {
742 CLEAR_ERROR_OCCURRED(tstate);
743
744 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT("'%s' cannot be interpreted as an integer", index);
745 return false;
746 }
747
748 Py_ssize_t index_ssize;
749#if PYTHON_VERSION < 0x300
750 if (PyInt_CheckExact(index_long)) {
751 index_ssize = PyInt_AS_LONG(index_long);
752 } else {
753 index_ssize = PyLong_AsSsize_t(index_long);
754 }
755#else
756 index_ssize = PyLong_AsSsize_t(index_long);
757#endif
758
759 Py_DECREF(index_long);
760
761 LIST_INSERT_CONST(list, index_ssize, item);
762 return true;
763}
764
765void LIST_INSERT_CONST(PyObject *list, Py_ssize_t index, PyObject *item) {
766 CHECK_OBJECT(list);
767 assert(PyList_CheckExact(list));
768 CHECK_OBJECT(item);
769
770 PyListObject *list_object = (PyListObject *)list;
771
772 Py_ssize_t n = Py_SIZE(list_object);
773
774 // Expand the list by needed space.
775 if (LIST_RESIZE(list_object, n + 1) == false) {
776 abort();
777 }
778
779 // Negative values and overflow for for index are handled here.
780 if (index < 0) {
781 index += n;
782 if (index < 0) {
783 index = 0;
784 }
785 }
786 if (index > n) {
787 index = n;
788 }
789
790 // Shift the items behind the insert index.
791 PyObject **items = list_object->ob_item;
792
793 for (Py_ssize_t i = n; --i >= index;) {
794 items[i + 1] = items[i];
795 }
796
797 Py_INCREF(item);
798 items[index] = item;
799}
800
801static void _Nuitka_ReverseObjectsSlice(PyObject **lo, PyObject **hi) {
802 assert(lo != NULL && hi != NULL);
803
804 hi -= 1;
805
806 while (lo < hi) {
807 {
808 PyObject *t = *lo;
809 *lo = *hi;
810 *hi = t;
811 }
812
813 lo += 1;
814 hi -= 1;
815 }
816}
817
818void LIST_REVERSE(PyObject *list) {
819 CHECK_OBJECT(list);
820 assert(PyList_CheckExact(list));
821
822 PyListObject *list_object = (PyListObject *)list;
823
824 if (Py_SIZE(list_object) > 1) {
825 _Nuitka_ReverseObjectsSlice(list_object->ob_item, list_object->ob_item + Py_SIZE(list_object));
826 }
827}
828
829#if PYTHON_VERSION >= 0x300 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT)
830static bool allocateListItems(PyListObject *list, Py_ssize_t size) {
831 PyObject **items = PyMem_New(PyObject *, size);
832
833 if (unlikely(items == NULL)) {
834 PyErr_NoMemory();
835 return false;
836 }
837
838 list->ob_item = items;
839 list->allocated = size;
840
841 return true;
842}
843
844#endif
845
846PyObject *MAKE_LIST(PyThreadState *tstate, PyObject *iterable) {
847 // Can leave the size hinting to later functions, because the list is allocated empty without
848 // items, and when then extending, etc. length hints can be used.
849 PyObject *list = MAKE_LIST_EMPTY(tstate, 0);
850
851#if _NUITKA_EXPERIMENTAL_DISABLE_LIST_OPT
852 PyObject *result = _PyList_Extend((PyListObject *)list, iterable);
853 if (result == NULL) {
854 Py_DECREF(list);
855 return NULL;
856 } else {
857 Py_DECREF(result);
858 return list;
859 }
860#else
861 Py_INCREF(iterable);
862
863#if PYTHON_VERSION >= 0x300
864 if (Nuitka_PyObject_HasLen(iterable)) {
865 Py_ssize_t iter_len = Nuitka_PyObject_Size(iterable);
866
867 if (unlikely(iter_len == -1)) {
868 if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
869 return NULL;
870 }
871
872 CLEAR_ERROR_OCCURRED(tstate);
873 }
874
875 if (iter_len > 0) {
876 if (allocateListItems((PyListObject *)list, iter_len) == false) {
877 return NULL;
878 }
879 }
880 }
881#endif
882
883 bool res = LIST_EXTEND_FROM_ITERABLE(tstate, list, iterable);
884
885 Py_DECREF(iterable);
886
887 if (unlikely(res == false)) {
888 Py_DECREF(list);
889 return NULL;
890 }
891
892 return list;
893#endif
894}
895
896#include "HelpersListsGenerated.c"
897// Part of "Nuitka", an optimizing Python compiler that is compatible and
898// integrates with CPython, but also works on its own.
899//
900// Licensed under the Apache License, Version 2.0 (the "License");
901// you may not use this file except in compliance with the License.
902// You may obtain a copy of the License at
903//
904// http://www.apache.org/licenses/LICENSE-2.0
905//
906// Unless required by applicable law or agreed to in writing, software
907// distributed under the License is distributed on an "AS IS" BASIS,
908// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
909// See the License for the specific language governing permissions and
910// limitations under the License.