diff --git a/stdlib/src/faulthandler.rs b/stdlib/src/faulthandler.rs
index 06c893a3a..927ecd94a 100644
--- a/stdlib/src/faulthandler.rs
+++ b/stdlib/src/faulthandler.rs
@@ -2,11 +2,9 @@ pub(crate) use decl::make_module;
#[pymodule(name = "faulthandler")]
mod decl {
- use crate::vm::{
- frame::FrameRef, function::OptionalArg, stdlib::sys::PyStderr, VirtualMachine,
- };
+ use crate::vm::{frame::Frame, function::OptionalArg, stdlib::sys::PyStderr, VirtualMachine};
- fn dump_frame(frame: &FrameRef, vm: &VirtualMachine) {
+ fn dump_frame(frame: &Frame, vm: &VirtualMachine) {
let stderr = PyStderr(vm);
writeln!(
stderr,
diff --git a/vm/src/builtins/frame.rs b/vm/src/builtins/frame.rs
index 10f9a1071..f08767af9 100644
--- a/vm/src/builtins/frame.rs
+++ b/vm/src/builtins/frame.rs
@@ -16,9 +16,6 @@ pub fn init(context: &Context) {
Frame::extend_class(context, context.types.frame_type);
}
-#[pyclass(with(Constructor, PyRef, Representable))]
-impl Frame {}
-
impl Unconstructible for Frame {}
impl Representable for Frame {
@@ -34,61 +31,46 @@ impl Representable for Frame {
}
}
-#[pyclass]
-impl PyRef {
+#[pyclass(with(Constructor, Py))]
+impl Frame {
#[pymethod]
- fn clear(self) {
+ fn clear(&self) {
// TODO
}
#[pygetset]
- fn f_globals(self) -> PyDictRef {
+ fn f_globals(&self) -> PyDictRef {
self.globals.clone()
}
#[pygetset]
- fn f_locals(self, vm: &VirtualMachine) -> PyResult {
+ fn f_locals(&self, vm: &VirtualMachine) -> PyResult {
self.locals(vm).map(Into::into)
}
#[pygetset]
- pub fn f_code(self) -> PyRef {
+ pub fn f_code(&self) -> PyRef {
self.code.clone()
}
#[pygetset]
- pub fn f_back(self, vm: &VirtualMachine) -> Option {
- // TODO: actually store f_back inside Frame struct
-
- // get the frame in the frame stack that appears before this one.
- // won't work if this frame isn't in the frame stack, hence the todo above
- vm.frames
- .borrow()
- .iter()
- .rev()
- .skip_while(|p| !p.is(&self))
- .nth(1)
- .cloned()
- }
-
- #[pygetset]
- fn f_lasti(self) -> u32 {
+ fn f_lasti(&self) -> u32 {
self.lasti()
}
#[pygetset]
- pub fn f_lineno(self) -> usize {
+ pub fn f_lineno(&self) -> usize {
self.current_location().row()
}
#[pygetset]
- fn f_trace(self) -> PyObjectRef {
+ fn f_trace(&self) -> PyObjectRef {
let boxed = self.trace.lock();
boxed.clone()
}
#[pygetset(setter)]
- fn set_f_trace(self, value: PySetterValue, vm: &VirtualMachine) {
+ fn set_f_trace(&self, value: PySetterValue, vm: &VirtualMachine) {
let mut storage = self.trace.lock();
*storage = value.unwrap_or_none(vm);
}
@@ -126,3 +108,21 @@ impl PyRef {
}
}
}
+
+#[pyclass]
+impl Py {
+ #[pygetset]
+ pub fn f_back(&self, vm: &VirtualMachine) -> Option> {
+ // TODO: actually store f_back inside Frame struct
+
+ // get the frame in the frame stack that appears before this one.
+ // won't work if this frame isn't in the frame stack, hence the todo above
+ vm.frames
+ .borrow()
+ .iter()
+ .rev()
+ .skip_while(|p| !p.is(self.as_object()))
+ .nth(1)
+ .cloned()
+ }
+}
diff --git a/vm/src/frame.rs b/vm/src/frame.rs
index 821a02b3c..d5c77c0e3 100644
--- a/vm/src/frame.rs
+++ b/vm/src/frame.rs
@@ -164,24 +164,20 @@ impl Frame {
temporary_refs: PyMutex::new(vec![]),
}
}
-}
-impl FrameRef {
- #[inline(always)]
- fn with_exec(&self, f: impl FnOnce(ExecutingFrame) -> R) -> R {
- let mut state = self.state.lock();
- let exec = ExecutingFrame {
- code: &self.code,
- fastlocals: &self.fastlocals,
- cells_frees: &self.cells_frees,
- locals: &self.locals,
- globals: &self.globals,
- builtins: &self.builtins,
- lasti: &self.lasti,
- object: self,
- state: &mut state,
- };
- f(exec)
+ pub fn current_location(&self) -> bytecode::Location {
+ self.code.locations[self.lasti() as usize - 1]
+ }
+
+ pub fn lasti(&self) -> u32 {
+ #[cfg(feature = "threading")]
+ {
+ self.lasti.load(atomic::Ordering::Relaxed)
+ }
+ #[cfg(not(feature = "threading"))]
+ {
+ self.lasti.get()
+ }
}
pub fn locals(&self, vm: &VirtualMachine) -> PyResult {
@@ -221,6 +217,25 @@ impl FrameRef {
}
Ok(locals.clone())
}
+}
+
+impl Py {
+ #[inline(always)]
+ fn with_exec(&self, f: impl FnOnce(ExecutingFrame) -> R) -> R {
+ let mut state = self.state.lock();
+ let exec = ExecutingFrame {
+ code: &self.code,
+ fastlocals: &self.fastlocals,
+ cells_frees: &self.cells_frees,
+ locals: &self.locals,
+ globals: &self.globals,
+ builtins: &self.builtins,
+ lasti: &self.lasti,
+ object: self,
+ state: &mut state,
+ };
+ f(exec)
+ }
// #[cfg_attr(feature = "flame-it", flame("Frame"))]
pub fn run(&self, vm: &VirtualMachine) -> PyResult {
@@ -250,34 +265,19 @@ impl FrameRef {
self.with_exec(|mut exec| exec.gen_throw(vm, exc_type, exc_val, exc_tb))
}
- pub fn current_location(&self) -> bytecode::Location {
- self.code.locations[self.lasti() as usize - 1]
- }
-
pub fn yield_from_target(&self) -> Option {
self.with_exec(|exec| exec.yield_from_target().map(PyObject::to_owned))
}
- pub fn lasti(&self) -> u32 {
- #[cfg(feature = "threading")]
- {
- self.lasti.load(atomic::Ordering::Relaxed)
- }
- #[cfg(not(feature = "threading"))]
- {
- self.lasti.get()
- }
- }
-
pub fn is_internal_frame(&self) -> bool {
- let code = self.clone().f_code();
+ let code = self.f_code();
let filename = code.co_filename();
filename.as_str().contains("importlib") && filename.as_str().contains("_bootstrap")
}
pub fn next_external_frame(&self, vm: &VirtualMachine) -> Option {
- self.clone().f_back(vm).map(|mut back| loop {
+ self.f_back(vm).map(|mut back| loop {
back = if let Some(back) = back.to_owned().f_back(vm) {
back
} else {
@@ -300,7 +300,7 @@ struct ExecutingFrame<'a> {
locals: &'a ArgMapping,
globals: &'a PyDictRef,
builtins: &'a PyDictRef,
- object: &'a FrameRef,
+ object: &'a Py,
lasti: &'a Lasti,
state: &'a mut FrameState,
}
@@ -376,8 +376,12 @@ impl ExecutingFrame<'_> {
let loc = frame.code.locations[idx];
let next = exception.traceback();
- let new_traceback =
- PyTraceback::new(next, frame.object.clone(), frame.lasti(), loc.row());
+ let new_traceback = PyTraceback::new(
+ next,
+ frame.object.to_owned(),
+ frame.lasti(),
+ loc.row(),
+ );
vm_trace!("Adding to traceback: {:?} {:?}", new_traceback, loc.row());
exception.set_traceback(Some(new_traceback.into_ref(vm)));