Replace escaped flag with take_ownership · RustPython/RustPython@47d4fda · GitHub
Skip to content

Commit 47d4fda

Browse files
committed
Replace escaped flag with take_ownership
gi_frame returns the frame object. Close uses a uniquely-referenced check to clear locals or take_ownership onto a husk. frame.clear() finalizes a generator-owned frame and only clears FRAME_OBJECT frames. close() leaves the generator suspended when it yields on GeneratorExit. Assisted-by: Grok:grok-4.6
1 parent 5a708a5 commit 47d4fda

7 files changed

Lines changed: 94 additions & 86 deletions

File tree

crates/vm/src/builtins/asyncgenerator.rs

Lines changed: 1 addition & 3 deletions

crates/vm/src/builtins/coroutine.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ impl PyCoroutine {
9696
if self.inner.closed() {
9797
None
9898
} else {
99-
let frame = self.inner.frame();
100-
frame.mark_escaped();
101-
Some(frame)
99+
Some(self.inner.frame())
102100
}
103101
}
104102
#[pygetset]

crates/vm/src/builtins/frame.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -778,10 +778,8 @@ impl Py<FrameObject> {
778778
);
779779
match owner {
780780
FrameOwner::Generator => {
781-
// Generator frame: check if suspended (lasti > 0 means
782-
// FRAME_SUSPENDED). lasti == 0 means FRAME_CREATED and
783-
// can be cleared. Finalize the owner so a never-started
784-
// coroutine emits its never-awaited warning.
781+
// FRAME_SUSPENDED (lasti > 0) cannot be cleared. FRAME_CREATED
782+
// and finished frames go through the owner finalizer.
785783
if self.lasti() != 0 {
786784
return Err(vm.new_runtime_error("cannot clear a suspended frame"));
787785
}
@@ -794,14 +792,12 @@ impl Py<FrameObject> {
794792
let _ = PyGenerator::del(generator, vm);
795793
}
796794
}
795+
return Ok(());
797796
}
798797
FrameOwner::Thread => {
799-
// Thread-owned frame: always executing, cannot clear.
800798
return Err(vm.new_runtime_error("cannot clear an executing frame"));
801799
}
802800
FrameOwner::FrameObject => {
803-
// Check if this materialized frame is backed by a live
804-
// stack-allocated iframe — if so, the frame is executing.
805801
if !self.find_live_source_iframe().is_null() {
806802
return Err(vm.new_runtime_error("cannot clear an executing frame"));
807803
}
@@ -849,7 +845,6 @@ impl Py<FrameObject> {
849845
#[pygetset]
850846
fn f_locals(&self, vm: &VirtualMachine) -> PyResult {
851847
if self.uses_locals_proxy(vm)? {
852-
self.mark_escaped();
853848
let proxy = crate::builtins::FrameLocalsProxy::new(self.to_owned());
854849
Ok(proxy.into_ref(&vm.ctx).into())
855850
} else {
@@ -886,7 +881,6 @@ impl Py<FrameObject> {
886881
// Check retained_back for frames whose callers have returned
887882
let retained = self.iframe().cold().retained_back.lock().clone();
888883
if let Some(frame) = retained {
889-
frame.mark_escaped();
890884
return Some(frame);
891885
}
892886
return None;
@@ -902,7 +896,6 @@ impl Py<FrameObject> {
902896
if core::ptr::eq(cur, prev) {
903897
let iframe_ref = unsafe { &*cur };
904898
let fo = iframe_ref.materialize(vm);
905-
fo.mark_escaped();
906899
return Some(fo.to_owned());
907900
}
908901
cur = unsafe { (*cur).previous() };
@@ -912,7 +905,6 @@ impl Py<FrameObject> {
912905
// The caller already returned — check retained_back
913906
let retained = self.iframe().cold().retained_back.lock().clone();
914907
if let Some(frame) = retained {
915-
frame.mark_escaped();
916908
return Some(frame);
917909
}
918910

@@ -927,13 +919,11 @@ impl Py<FrameObject> {
927919
let prev_ref = unsafe { &*prev };
928920
// Fast path: already materialized.
929921
if let Some(fo) = prev_ref.frame_obj() {
930-
fo.mark_escaped();
931922
return Some(fo.to_owned());
932923
}
933924
// Slow path: copy the whole chain, linked through retained_back.
934925
// SAFETY: the world is stopped, so the owning thread is parked.
935926
let fo = unsafe { prev_ref.materialize_detached_chain(vm) };
936-
fo.mark_escaped();
937927
return Some(fo);
938928
}
939929

crates/vm/src/builtins/generator.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ impl PyGenerator {
7474
if self.inner.closed() {
7575
None
7676
} else {
77-
let frame = self.inner.frame();
78-
frame.mark_escaped();
79-
Some(frame)
77+
Some(self.inner.frame())
8078
}
8179
}
8280

crates/vm/src/coroutine.rs

Lines changed: 56 additions & 46 deletions

0 commit comments

Comments
 (0)