Skip to content

Commit 7d75c4e

Browse files
authored
Merge pull request RustPython#2079 from youknowone/small-int
small int cache for int.__new__
2 parents 0daf60a + d22234f commit 7d75c4e

5 files changed

Lines changed: 45 additions & 18 deletions

File tree

Lib/test/test_int.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def test_underscores(self):
233233
self.assertRaises(ValueError, int, "1__00")
234234
self.assertRaises(ValueError, int, "100_")
235235

236-
@support.cpython_only
236+
# @support.cpython_only
237237
def test_small_ints(self):
238238
# Bug #3236: Return small longs from PyLong_FromString
239239
self.assertIs(int('10'), 10)

Lib/test/test_long.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,6 @@ def test_small_ints_in_huge_calculation(self):
976976
self.assertIs(a + b, 1)
977977
self.assertIs(c - a, 1)
978978

979-
@unittest.expectedFailure
980979
def test_small_ints(self):
981980
for i in range(-5, 257):
982981
self.assertIs(i, i + 0)

vm/src/obj/objint.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use num_traits::{One, Pow, Signed, ToPrimitive, Zero};
99
use super::objbool::IntoPyBool;
1010
use super::objbytearray::PyByteArray;
1111
use super::objbytes::PyBytes;
12+
use super::objdict::PyDictRef;
1213
use super::objfloat;
1314
use super::objmemory::PyMemoryView;
1415
use super::objstr::{PyString, PyStringRef};
@@ -17,9 +18,8 @@ use crate::bytesinner::PyBytesInner;
1718
use crate::format::FormatSpec;
1819
use crate::function::{OptionalArg, PyFuncArgs};
1920
use crate::pyobject::{
20-
IdProtocol, IntoPyObject, IntoPyRef, IntoPyResult, PyArithmaticValue, PyClassImpl,
21-
PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
22-
TypeProtocol,
21+
IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, PyComparisonValue,
22+
PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
2323
};
2424
use crate::stdlib::array::PyArray;
2525
use crate::vm::VirtualMachine;
@@ -78,6 +78,23 @@ impl PyValue for PyInt {
7878
fn class(vm: &VirtualMachine) -> PyClassRef {
7979
vm.ctx.int_type()
8080
}
81+
82+
fn into_simple_object(self, vm: &VirtualMachine) -> PyObjectRef {
83+
vm.ctx.new_int(self.value)
84+
}
85+
86+
fn into_object(
87+
self,
88+
vm: &VirtualMachine,
89+
cls: PyClassRef,
90+
dict: Option<PyDictRef>,
91+
) -> PyObjectRef {
92+
if cls.is(&Self::class(vm)) {
93+
vm.ctx.new_int(self.value)
94+
} else {
95+
PyObject::new(self, cls, dict)
96+
}
97+
}
8198
}
8299

83100
macro_rules! impl_into_pyobject_int {
@@ -223,10 +240,10 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult {
223240
impl PyInt {
224241
fn with_value<T>(cls: PyClassRef, value: T, vm: &VirtualMachine) -> PyResult<PyIntRef>
225242
where
226-
T: Into<BigInt>,
243+
T: Into<BigInt> + ToPrimitive,
227244
{
228245
if cls.is(&vm.ctx.int_type()) {
229-
Ok(value.into().into_pyref(vm))
246+
Ok(PyRef::from_obj_unchecked(vm.ctx.new_int(value)))
230247
} else {
231248
PyInt::from(value).into_ref_with_type(vm, cls)
232249
}

vm/src/pyobject.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ where
11911191
T: PyValue + Sized,
11921192
{
11931193
fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
1194-
PyObject::new(self, T::class(vm), None)
1194+
PyValue::into_simple_object(self, vm)
11951195
}
11961196
}
11971197

@@ -1303,8 +1303,21 @@ pub trait PyValue: fmt::Debug + PyThreadingConstraint + Sized + 'static {
13031303

13041304
fn class(vm: &VirtualMachine) -> PyClassRef;
13051305

1306+
fn into_simple_object(self, vm: &VirtualMachine) -> PyObjectRef {
1307+
self.into_object(vm, Self::class(vm), None)
1308+
}
1309+
1310+
fn into_object(
1311+
self,
1312+
_vm: &VirtualMachine,
1313+
cls: PyClassRef,
1314+
dict: Option<PyDictRef>,
1315+
) -> PyObjectRef {
1316+
PyObject::new(self, cls, dict)
1317+
}
1318+
13061319
fn into_ref(self, vm: &VirtualMachine) -> PyRef<Self> {
1307-
self.into_ref_with_type_unchecked(Self::class(vm), None)
1320+
PyRef::from_obj_unchecked(self.into_simple_object(vm))
13081321
}
13091322

13101323
fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyClassRef) -> PyResult<PyRef<Self>> {
@@ -1315,17 +1328,13 @@ pub trait PyValue: fmt::Debug + PyThreadingConstraint + Sized + 'static {
13151328
} else {
13161329
Some(vm.ctx.new_dict())
13171330
};
1318-
PyRef::from_obj(PyObject::new(self, cls, dict), vm)
1331+
PyRef::from_obj(self.into_object(vm, cls, dict), vm)
13191332
} else {
13201333
let subtype = vm.to_str(&cls.obj)?;
13211334
let basetype = vm.to_str(&class.obj)?;
13221335
Err(vm.new_type_error(format!("{} is not a subtype of {}", subtype, basetype)))
13231336
}
13241337
}
1325-
1326-
fn into_ref_with_type_unchecked(self, cls: PyClassRef, dict: Option<PyDictRef>) -> PyRef<Self> {
1327-
PyRef::from_obj_unchecked(PyObject::new(self, cls, dict))
1328-
}
13291338
}
13301339

13311340
pub trait PyObjectPayload: Any + fmt::Debug + PyThreadingConstraint + 'static {

vm/src/vm.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ use crate::obj::objstr::{PyString, PyStringRef};
4040
use crate::obj::objtuple::PyTuple;
4141
use crate::obj::objtype::{self, PyClassRef};
4242
use crate::pyobject::{
43-
IdProtocol, ItemProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject,
44-
TryIntoRef, TypeProtocol,
43+
IdProtocol, ItemProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
44+
TryFromObject, TryIntoRef, TypeProtocol,
4545
};
4646
use crate::scope::Scope;
4747
use crate::stdlib;
@@ -415,8 +415,10 @@ impl VirtualMachine {
415415
) -> PyBaseExceptionRef {
416416
// TODO: add repr of args into logging?
417417
vm_trace!("New exception created: {}", exc_type.name);
418-
PyBaseException::new(args, self)
419-
.into_ref_with_type_unchecked(exc_type, Some(self.ctx.new_dict()))
418+
419+
let pyobj =
420+
PyBaseException::new(args, self).into_object(self, exc_type, Some(self.ctx.new_dict()));
421+
PyRef::from_obj_unchecked(pyobj)
420422
}
421423

422424
/// Instantiate an exception with no arguments.

0 commit comments

Comments
 (0)