Skip to content

Commit fb8f7b1

Browse files
committed
Store SystemExit.code in a struct field instead of the instance dict
1 parent 4d6ac3f commit fb8f7b1

1 file changed

Lines changed: 60 additions & 12 deletions

File tree

‎crates/vm/src/exceptions.rs‎

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -959,9 +959,7 @@ impl ExceptionZoo {
959959
"exceptions" => ctx.new_readonly_getset("exceptions", excs.base_exception_group, make_arg_getter(1)),
960960
});
961961

962-
extend_exception!(PySystemExit, ctx, excs.system_exit, {
963-
"code" => ctx.none(),
964-
});
962+
extend_exception!(PySystemExit, ctx, excs.system_exit);
965963
extend_exception!(PyKeyboardInterrupt, ctx, excs.keyboard_interrupt);
966964
extend_exception!(PyGeneratorExit, ctx, excs.generator_exit);
967965

@@ -1580,7 +1578,7 @@ pub(super) mod types {
15801578
tuple::IntoPyTuple,
15811579
},
15821580
convert::ToPyResult,
1583-
function::{ArgBytesLike, FuncArgs, KwArgs},
1581+
function::{ArgBytesLike, FuncArgs, KwArgs, PySetterValue},
15841582
set_attrs,
15851583
types::{Constructor, Initializer},
15861584
};
@@ -1611,14 +1609,51 @@ pub(super) mod types {
16111609
pub(super) args: PyRwLock<PyTupleRef>,
16121610
}
16131611

1614-
#[pyexception(name, base = PyBaseException, ctx = "system_exit")]
1615-
#[derive(Debug)]
1616-
#[repr(transparent)]
1617-
pub struct PySystemExit(PyBaseException);
1612+
#[pyexception(name, base = PyBaseException, ctx = "system_exit", traverse = "manual")]
1613+
#[repr(C)]
1614+
pub struct PySystemExit {
1615+
base: PyBaseException,
1616+
code: PyAtomicRef<Option<PyObject>>,
1617+
}
16181618

1619-
// SystemExit_init: has its own __init__ that sets the code attribute
1620-
#[pyexception(with(Initializer))]
1621-
impl PySystemExit {}
1619+
impl crate::class::PySubclass for PySystemExit {
1620+
type Base = PyBaseException;
1621+
fn as_base(&self) -> &Self::Base {
1622+
&self.base
1623+
}
1624+
}
1625+
1626+
unsafe impl Traverse for PySystemExit {
1627+
fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) {
1628+
self.base.traverse(tracer_fn);
1629+
if let Some(obj) = self.code.deref() {
1630+
tracer_fn(obj);
1631+
}
1632+
}
1633+
}
1634+
1635+
impl core::fmt::Debug for PySystemExit {
1636+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1637+
f.debug_struct("PySystemExit").finish_non_exhaustive()
1638+
}
1639+
}
1640+
1641+
#[pyexception(with(Constructor, Initializer))]
1642+
impl PySystemExit {
1643+
#[pygetset]
1644+
fn code(&self) -> Option<PyObjectRef> {
1645+
self.code.to_owned()
1646+
}
1647+
1648+
#[pygetset(setter)]
1649+
fn set_code(&self, value: PySetterValue, vm: &VirtualMachine) {
1650+
let code = match value {
1651+
PySetterValue::Assign(v) => Some(v),
1652+
PySetterValue::Delete => None,
1653+
};
1654+
self.code.swap_to_temporary_refs(code, vm);
1655+
}
1656+
}
16221657

16231658
impl Initializer for PySystemExit {
16241659
type Args = FuncArgs;
@@ -1630,7 +1665,8 @@ pub(super) mod types {
16301665
_ => vm.ctx.new_tuple(args.args.clone()).into(),
16311666
};
16321667
PyBaseException::slot_init(zelf.clone(), args, vm)?;
1633-
zelf.set_attr("code", code, vm)?;
1668+
let exc: &Py<Self> = zelf.downcast_ref::<Self>().unwrap();
1669+
exc.code.swap_to_temporary_refs(Some(code), vm);
16341670
Ok(())
16351671
}
16361672

@@ -1639,6 +1675,18 @@ pub(super) mod types {
16391675
}
16401676
}
16411677

1678+
impl Constructor for PySystemExit {
1679+
type Args = FuncArgs;
1680+
1681+
fn py_new(_cls: &Py<PyType>, args: FuncArgs, vm: &VirtualMachine) -> PyResult<Self> {
1682+
let base_exception = PyBaseException::new(args.args, vm);
1683+
Ok(Self {
1684+
base: base_exception,
1685+
code: None.into(),
1686+
})
1687+
}
1688+
}
1689+
16421690
#[pyexception(name, base = PyBaseException, ctx = "generator_exit", impl)]
16431691
#[derive(Debug)]
16441692
#[repr(transparent)]

0 commit comments

Comments
 (0)