Skip to content

Commit 3e92a7a

Browse files
committed
vm: add send_none fastpath for generator specialization
1 parent 727f3f1 commit 3e92a7a

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

crates/vm/src/coroutine.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,12 @@ impl Coro {
115115
result
116116
}
117117

118-
pub fn send(
118+
fn finalize_send_result(
119119
&self,
120120
jen: &PyObject,
121-
value: PyObjectRef,
121+
result: PyResult<ExecutionResult>,
122122
vm: &VirtualMachine,
123123
) -> PyResult<PyIterReturn> {
124-
if self.closed.load() {
125-
return Ok(PyIterReturn::StopIteration(None));
126-
}
127-
self.frame.locals_to_fast(vm)?;
128-
let value = if self.frame.lasti() > 0 {
129-
Some(value)
130-
} else if !vm.is_none(&value) {
131-
return Err(vm.new_type_error(format!(
132-
"can't send non-None value to a just-started {}",
133-
gen_name(jen, vm),
134-
)));
135-
} else {
136-
None
137-
};
138-
let result = self.run_with_context(jen, vm, |f| f.resume(value, vm));
139124
self.maybe_close(&result);
140125
match result {
141126
Ok(exec_res) => Ok(exec_res.into_iter_return(vm)),
@@ -158,6 +143,44 @@ impl Coro {
158143
}
159144
}
160145

146+
pub(crate) fn send_none(&self, jen: &PyObject, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
147+
if self.closed.load() {
148+
return Ok(PyIterReturn::StopIteration(None));
149+
}
150+
self.frame.locals_to_fast(vm)?;
151+
let value = if self.frame.lasti() > 0 {
152+
Some(vm.ctx.none())
153+
} else {
154+
None
155+
};
156+
let result = self.run_with_context(jen, vm, |f| f.resume(value, vm));
157+
self.finalize_send_result(jen, result, vm)
158+
}
159+
160+
pub fn send(
161+
&self,
162+
jen: &PyObject,
163+
value: PyObjectRef,
164+
vm: &VirtualMachine,
165+
) -> PyResult<PyIterReturn> {
166+
if self.closed.load() {
167+
return Ok(PyIterReturn::StopIteration(None));
168+
}
169+
self.frame.locals_to_fast(vm)?;
170+
let value = if self.frame.lasti() > 0 {
171+
Some(value)
172+
} else if !vm.is_none(&value) {
173+
return Err(vm.new_type_error(format!(
174+
"can't send non-None value to a just-started {}",
175+
gen_name(jen, vm),
176+
)));
177+
} else {
178+
None
179+
};
180+
let result = self.run_with_context(jen, vm, |f| f.resume(value, vm));
181+
self.finalize_send_result(jen, result, vm)
182+
}
183+
161184
pub fn throw(
162185
&self,
163186
jen: &PyObject,

crates/vm/src/frame.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3120,7 +3120,11 @@ impl ExecutingFrame<'_> {
31203120
let receiver = self.top_value();
31213121
let ret = if can_fast_send {
31223122
let coro = self.builtin_coro(receiver).unwrap();
3123-
coro.send(receiver, val, vm)?
3123+
if vm.is_none(&val) {
3124+
coro.send_none(receiver, vm)?
3125+
} else {
3126+
coro.send(receiver, val, vm)?
3127+
}
31243128
} else {
31253129
self._send(receiver, val, vm)?
31263130
};
@@ -5301,7 +5305,7 @@ impl ExecutingFrame<'_> {
53015305
self.execute_for_iter(vm, target)?;
53025306
return Ok(None);
53035307
}
5304-
match generator.as_coro().send(iter, vm.ctx.none(), vm) {
5308+
match generator.as_coro().send_none(iter, vm) {
53055309
Ok(PyIterReturn::Return(value)) => {
53065310
self.push_value(value);
53075311
}

0 commit comments

Comments
 (0)