Skip to content
Prev Previous commit
Next Next commit
Consolidate with_recursion in _cmp to single guard
Move the recursion depth check to wrap the entire _cmp body
instead of each individual call_cmp direction, reducing Cell
read/write pairs and scopeguard overhead per comparison.
  • Loading branch information
youknowone committed Mar 1, 2026
commit 0af466c24cd45910bac471e10123a18861ad82c2
21 changes: 15 additions & 6 deletions crates/vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,24 @@ impl PyObject {

// Perform a comparison, raising TypeError when the requested comparison
// operator is not supported.
// see: CPython PyObject_RichCompare
// see: CPython PyObject_RichCompare / do_richcompare
#[inline] // called by ExecutingFrame::execute_compare with const op
fn _cmp(
&self,
other: &Self,
op: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<Either<PyObjectRef, bool>> {
// Single recursion guard for the entire comparison (matching CPython's
// Py_EnterRecursiveCallTstate placement in do_richcompare).
vm.with_recursion("in comparison", || self._cmp_inner(other, op, vm))
}

fn _cmp_inner(
&self,
other: &Self,
op: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<Either<PyObjectRef, bool>> {
let swapped = op.swapped();
let call_cmp = |obj: &Self, other: &Self, op| {
Expand All @@ -302,19 +313,17 @@ impl PyObject {
!self_class.is(other_class) && other_class.fast_issubclass(self_class)
};
if is_strict_subclass {
let res = vm.with_recursion("in comparison", || call_cmp(other, self, swapped))?;
let res = call_cmp(other, self, swapped)?;
checked_reverse_op = true;
if let PyArithmeticValue::Implemented(x) = res {
return Ok(x);
}
}
if let PyArithmeticValue::Implemented(x) =
vm.with_recursion("in comparison", || call_cmp(self, other, op))?
{
if let PyArithmeticValue::Implemented(x) = call_cmp(self, other, op)? {
return Ok(x);
}
if !checked_reverse_op {
let res = vm.with_recursion("in comparison", || call_cmp(other, self, swapped))?;
let res = call_cmp(other, self, swapped)?;
if let PyArithmeticValue::Implemented(x) = res {
return Ok(x);
}
Expand Down