Skip to content

Commit 009a028

Browse files
committed
Small int cache like cpython
1 parent b769675 commit 009a028

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

tests/snippets/ints.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,3 +306,8 @@ def __int__(self):
306306

307307
with assert_raises(SyntaxError):
308308
exec(src)
309+
310+
# Small int cache in [-5..256]
311+
assert 1 is 1
312+
x = 6
313+
assert 5 is (x-1)

vm/src/pyobject.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::rc::Rc;
88

99
use num_bigint::BigInt;
1010
use num_complex::Complex64;
11-
use num_traits::{One, Zero};
11+
use num_traits::{One, ToPrimitive, Zero};
1212

1313
use crate::bytecode;
1414
use crate::dictdatatype::DictKey;
@@ -92,6 +92,9 @@ impl fmt::Display for PyObject<dyn PyObjectPayload> {
9292
}
9393
}
9494

95+
const INT_CACHE_POOL_MIN: i32 = -5;
96+
const INT_CACHE_POOL_MAX: i32 = 256;
97+
9598
#[derive(Debug)]
9699
pub struct PyContext {
97100
pub true_value: PyIntRef,
@@ -104,6 +107,7 @@ pub struct PyContext {
104107

105108
pub types: TypeZoo,
106109
pub exceptions: exceptions::ExceptionZoo,
110+
pub int_cache_pool: Vec<PyObjectRef>,
107111
}
108112

109113
pub type PyNotImplementedRef = PyRef<PyNotImplemented>;
@@ -149,6 +153,10 @@ impl PyContext {
149153
create_type("NotImplementedType", &types.type_type, &types.object_type);
150154
let not_implemented = create_object(PyNotImplemented, &not_implemented_type);
151155

156+
let int_cache_pool = (INT_CACHE_POOL_MIN..=INT_CACHE_POOL_MAX)
157+
.map(|v| create_object(PyInt::new(BigInt::from(v)), &types.int_type).into_object())
158+
.collect();
159+
152160
let true_value = create_object(PyInt::new(BigInt::one()), &types.bool_type);
153161
let false_value = create_object(PyInt::new(BigInt::zero()), &types.bool_type);
154162

@@ -159,12 +167,13 @@ impl PyContext {
159167
false_value,
160168
not_implemented,
161169
none,
170+
empty_tuple,
162171
ellipsis,
163172
ellipsis_type,
164173

165174
types,
166175
exceptions,
167-
empty_tuple,
176+
int_cache_pool,
168177
};
169178
initialize_types(&context);
170179

@@ -364,7 +373,15 @@ impl PyContext {
364373
self.types.object_type.clone()
365374
}
366375

376+
#[inline]
367377
pub fn new_int<T: Into<BigInt>>(&self, i: T) -> PyObjectRef {
378+
let i = i.into();
379+
if let Some(i) = i.to_i32() {
380+
if i >= INT_CACHE_POOL_MIN && i <= INT_CACHE_POOL_MAX {
381+
let inner_idx = (i - INT_CACHE_POOL_MIN) as usize;
382+
return self.int_cache_pool[inner_idx].clone();
383+
}
384+
}
368385
PyObject::new(PyInt::new(i), self.int_type(), None)
369386
}
370387

vm/src/vm.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,11 +293,13 @@ impl VirtualMachine {
293293
}
294294

295295
/// Create a new python int object.
296+
#[inline]
296297
pub fn new_int<T: Into<BigInt>>(&self, i: T) -> PyObjectRef {
297298
self.ctx.new_int(i)
298299
}
299300

300301
/// Create a new python bool object.
302+
#[inline]
301303
pub fn new_bool(&self, b: bool) -> PyObjectRef {
302304
self.ctx.new_bool(b)
303305
}

0 commit comments

Comments
 (0)