Skip to content

Commit cfd1edb

Browse files
committed
Add PySlice freelist (max 1, matching PySlice_MAXFREELIST)
1 parent a57152c commit cfd1edb

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

crates/vm/src/builtins/slice.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// sliceobject.{h,c} in CPython
22
// spell-checker:ignore sliceobject
3+
use core::cell::Cell;
4+
use core::ptr::NonNull;
35
use rustpython_common::wtf8::{Wtf8Buf, wtf8_concat};
46

57
use super::{PyGenericAlias, PyStrRef, PyTupleRef, PyType, PyTypeRef};
@@ -23,11 +25,45 @@ pub struct PySlice {
2325
pub step: Option<PyObjectRef>,
2426
}
2527

28+
// CPython caches only 1 slice object (PySlice_MAXFREELIST = 1)
29+
const PYSLICE_MAXFREELIST: usize = 1;
30+
31+
thread_local! {
32+
static SLICE_FREELIST: Cell<Vec<*mut PyObject>> = const { Cell::new(Vec::new()) };
33+
}
34+
2635
impl PyPayload for PySlice {
36+
const HAS_FREELIST: bool = true;
37+
2738
#[inline]
2839
fn class(ctx: &Context) -> &'static Py<PyType> {
2940
ctx.types.slice_type
3041
}
42+
43+
#[inline]
44+
unsafe fn freelist_push(obj: *mut PyObject) -> bool {
45+
SLICE_FREELIST.with(|fl| {
46+
let mut list = fl.take();
47+
let stored = if list.len() < PYSLICE_MAXFREELIST {
48+
list.push(obj);
49+
true
50+
} else {
51+
false
52+
};
53+
fl.set(list);
54+
stored
55+
})
56+
}
57+
58+
#[inline]
59+
unsafe fn freelist_pop() -> Option<NonNull<PyObject>> {
60+
SLICE_FREELIST.with(|fl| {
61+
let mut list = fl.take();
62+
let result = list.pop().map(|p| unsafe { NonNull::new_unchecked(p) });
63+
fl.set(list);
64+
result
65+
})
66+
}
3167
}
3268

3369
#[pyclass(with(Comparable, Representable, Hashable))]

0 commit comments

Comments
 (0)