Lightweight frame execution for generator/coroutine resume. Pushes to the thread frame stack and fires trace/profile events, but skips the thread exception update for performance.
(
&self,
frame: &FrameRef,
exc: Option<PyBaseExceptionRef>,
f: F,
)
| 1628 | /// Pushes to the thread frame stack and fires trace/profile events, |
| 1629 | /// but skips the thread exception update for performance. |
| 1630 | pub fn resume_gen_frame<R, F: FnOnce(&Py<Frame>) -> PyResult<R>>( |
| 1631 | &self, |
| 1632 | frame: &FrameRef, |
| 1633 | exc: Option<PyBaseExceptionRef>, |
| 1634 | f: F, |
| 1635 | ) -> PyResult<R> { |
| 1636 | self.check_recursive_call("")?; |
| 1637 | if self.check_c_stack_overflow() { |
| 1638 | return Err(self.new_recursion_error(String::new())); |
| 1639 | } |
| 1640 | self.recursion_depth.update(|d| d + 1); |
| 1641 | |
| 1642 | // SAFETY: frame (&FrameRef) stays alive for the duration, so NonNull is valid until pop. |
| 1643 | let fp = FramePtr(NonNull::from(&**frame)); |
| 1644 | self.frames.borrow_mut().push(fp); |
| 1645 | #[cfg(feature = "threading")] |
| 1646 | crate::vm::thread::push_thread_frame(fp); |
| 1647 | let old_frame = crate::vm::thread::set_current_frame((&***frame) as *const Frame); |
| 1648 | frame.previous.store( |
| 1649 | old_frame as *mut Frame, |
| 1650 | core::sync::atomic::Ordering::Relaxed, |
| 1651 | ); |
| 1652 | // Inline exception push without thread exception update |
| 1653 | self.exceptions.borrow_mut().stack.push(exc); |
| 1654 | let old_owner = frame.owner.swap( |
| 1655 | crate::frame::FrameOwner::Thread as i8, |
| 1656 | core::sync::atomic::Ordering::AcqRel, |
| 1657 | ); |
| 1658 | |
| 1659 | // Ensure cleanup on panic: restore owner, pop exception, frame chain, frames Vec, |
| 1660 | // and recursion depth. |
| 1661 | scopeguard::defer! { |
| 1662 | frame.owner.store(old_owner, core::sync::atomic::Ordering::Release); |
| 1663 | self.exceptions.borrow_mut().stack |
| 1664 | .pop() |
| 1665 | .expect("pop_exception() without nested exc stack"); |
| 1666 | crate::vm::thread::set_current_frame(old_frame); |
| 1667 | self.frames.borrow_mut().pop(); |
| 1668 | #[cfg(feature = "threading")] |
| 1669 | crate::vm::thread::pop_thread_frame(); |
| 1670 | |
| 1671 | self.recursion_depth.update(|d| d - 1); |
| 1672 | } |
| 1673 | |
| 1674 | self.dispatch_traced_frame(frame, |frame| f(frame)) |
| 1675 | } |
| 1676 | |
| 1677 | /// Fire trace/profile 'call' and 'return' events around a frame body. |
| 1678 | /// |
no test coverage detected