Skip to content

Commit 32f1a36

Browse files
committed
working version
1 parent f799722 commit 32f1a36

3 files changed

Lines changed: 32 additions & 27 deletions

File tree

‎Include/internal/pycore_freelist_state.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ extern "C" {
1010

1111
# define PyTuple_MAXSAVESIZE 20 // Largest tuple to save on freelist
1212
# define Py_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
13-
# define PyList_MAXSAVESIZE 10 // Largest list size to save on freelist (minus one)
13+
# define PyList_MAXSAVESIZE 13 // Largest list size to save on freelist (minus one)
1414
# define Py_small_lists_MAXFREELIST 40
1515
# define Py_lists_MAXFREELIST 80
1616
# define Py_list_iters_MAXFREELIST 10

‎Objects/listobject.c‎

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -233,17 +233,14 @@ static inline int
233233
maybe_small_list_freelist_push(PyObject *self)
234234
{
235235
assert(PyList_CheckExact(self));
236-
assert(0);
237236

238237
PyListObject *op = (PyListObject *)self;
239238
PyObject **ob_item = _Py_atomic_load_ptr(&op->ob_item);
240239

241-
242-
Py_ssize_t cap = op->allocated; // what is the difference between allocated and capacity in the FT build?
243-
244-
printf("maybe_small_list_freelist_push: cap %d\n", cap);
245-
if (cap < PyList_MAXSAVESIZE) {
246-
return _Py_FREELIST_PUSH(small_lists[cap], self, Py_small_lists_MAXFREELIST);
240+
Py_ssize_t allocated = op->allocated;
241+
if (allocated < PyList_MAXSAVESIZE) {
242+
return _Py_FREELIST_PUSH(small_lists[allocated], self, Py_small_lists_MAXFREELIST);
243+
//printf("maybe_small_list_freelist_push: allocated %d (mod %d), size %d, id %p\n", (int)allocated, op->allocated, (int)PyList_Size(self), (void *)self);
247244
}
248245
return 0;
249246
}
@@ -257,19 +254,23 @@ PyList_New(Py_ssize_t size)
257254
return NULL;
258255
}
259256

260-
PyListObject *op;
257+
PyListObject *op=0;
261258

262-
if (size < PyList_MAXSAVESIZE ) {
263-
op = 0;
264-
//op = (PyListObject *)_Py_FREELIST_POP(PyLongObject, small_lists[size]);
265-
}
266-
if (op) {
267-
// allocated with ob_item still allocated. we do need to set to zero?
268-
if ( size>0) {
269-
memset(&op->ob_item, 0, size * sizeof(PyObject *));
259+
if (size < PyList_MAXSAVESIZE) {
260+
op = (PyListObject *)_Py_FREELIST_POP(PyLongObject, small_lists[size]);
261+
if (op) {
262+
// allocated with ob_item still allocated, but we need to set the other fields
263+
Py_SET_SIZE(op, size);
264+
if ( size>0) {
265+
memset(op->ob_item, 0, size * sizeof(PyObject *));
266+
}
267+
//printf("obtained list from small_lists[%d] (id %p, op->allocated %d, size %d, PyList_Size %d)\n", (int) size, op, (int)op->allocated, (int)size, (int)PyList_Size( (PyObject*)op));
268+
assert (op->allocated >= size);
270269
}
270+
op=0;
271271
}
272-
else {
272+
if (!op) {
273+
// do we still need this freelist? if so, we could store it at small_lists[PyList_MAXSAVESIZE-1] with some special casing
273274
op = _Py_FREELIST_POP(PyListObject, lists);
274275
if (op == NULL) {
275276
op = PyObject_GC_New(PyListObject, &PyList_Type);
@@ -551,12 +552,13 @@ PyList_Append(PyObject *op, PyObject *newitem)
551552

552553
/* Methods */
553554

554-
void small_list_freelist_free(PyObject *self)
555+
void small_list_freelist_free(void *obj)
555556
{
556-
assert(0);
557-
printf("small_list_freelist_free\n");
558-
assert(PyLong_CheckExact(self));
557+
PyObject *self = (PyObject *)obj;
558+
559+
assert(PyList_CheckExact(self));
559560
PyListObject *op = (PyListObject *)self;
561+
//printf("small_list_freelist_free: (op->allocated %d, size %d)\n", (int)op->allocated, (int)PyList_Size(self));
560562
if (op->ob_item != NULL) {
561563
free_list_items(op->ob_item, false);
562564
}
@@ -580,19 +582,22 @@ list_dealloc(PyObject *self)
580582
Py_XDECREF(op->ob_item[i]);
581583
}
582584
}
583-
if (0 && maybe_small_list_freelist_push(self) ) {
584-
return;
585+
if (PyList_CheckExact(op)) {
586+
if( maybe_small_list_freelist_push(self) ) {
587+
goto end;
588+
}
585589
}
586-
587590
if (op->ob_item != NULL) {
588591
free_list_items(op->ob_item, false);
589592
}
590593
if (PyList_CheckExact(op)) {
591-
_Py_FREELIST_FREE(lists, op, PyObject_GC_Del);
594+
_Py_FREELIST_FREE(lists, op, PyObject_GC_Del);
592595
}
593596
else {
594597
PyObject_GC_Del(op);
595598
}
599+
600+
end:
596601
Py_TRASHCAN_END
597602
}
598603

‎Objects/object.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ free_object(void *obj)
914914
Py_DECREF(tp);
915915
}
916916

917-
extern void small_list_freelist_free(PyObject *);
917+
extern void small_list_freelist_free(void *);
918918

919919
void
920920
_PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)

0 commit comments

Comments
 (0)