Skip to content

Commit ed60687

Browse files
committed
Replace all of callable operations to PyCallable
1 parent 66d9514 commit ed60687

File tree

3 files changed

+92
-83
lines changed

3 files changed

+92
-83
lines changed

vm/src/function/protocol.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,30 @@ use crate::{
44
convert::ToPyObject,
55
identifier,
66
protocol::{PyIter, PyIterIter, PyMapping, PyMappingMethods},
7-
types::AsMapping,
7+
types::{AsMapping, GenericMethod},
88
AsObject, PyObject, PyObjectRef, PyPayload, PyResult, TryFromObject, VirtualMachine,
99
};
1010
use std::{borrow::Borrow, marker::PhantomData, ops::Deref};
1111

12-
#[derive(Clone, Debug)]
12+
#[derive(Clone)]
1313
pub struct ArgCallable {
14-
obj: PyObjectRef, // FIXME: PyCallable
14+
obj: PyObjectRef,
15+
call: GenericMethod,
1516
}
1617

1718
impl ArgCallable {
1819
#[inline(always)]
1920
pub fn invoke(&self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
20-
vm.invoke(&self.obj, args)
21+
(self.call)(&self.obj, args.into_args(vm), vm)
22+
}
23+
}
24+
25+
impl std::fmt::Debug for ArgCallable {
26+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27+
f.debug_struct("ArgCallable")
28+
.field("obj", &self.obj)
29+
.field("call", &format!("{:08x}", self.call as usize))
30+
.finish()
2131
}
2232
}
2333

@@ -44,11 +54,11 @@ impl From<ArgCallable> for PyObjectRef {
4454

4555
impl TryFromObject for ArgCallable {
4656
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
47-
if obj.is_callable() {
48-
Ok(ArgCallable { obj })
49-
} else {
50-
Err(vm.new_type_error(format!("'{}' object is not callable", obj.class().name())))
51-
}
57+
let Some(callable) = obj.to_callable() else {
58+
return Err(vm.new_type_error(format!("'{}' object is not callable", obj.class().name())));
59+
};
60+
let call = callable.call;
61+
Ok(ArgCallable { obj, call })
5262
}
5363
}
5464

vm/src/protocol/callable.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
function::IntoFuncArgs,
33
types::GenericMethod,
4-
{PyObject, PyResult, VirtualMachine}
4+
{AsObject, PyObject, PyResult, VirtualMachine},
55
};
66

77
impl PyObject {
@@ -28,6 +28,70 @@ impl<'a> PyCallable<'a> {
2828
}
2929

3030
pub fn invoke(&self, args: impl IntoFuncArgs, vm: &VirtualMachine) -> PyResult {
31-
(self.call)(self.obj, args.into_args(vm), vm)
31+
vm.trace_event(TraceEvent::Call)?;
32+
let result = (self.call)(self.obj, args.into_args(vm), vm);
33+
vm.trace_event(TraceEvent::Return)?;
34+
result
35+
}
36+
}
37+
38+
/// Trace events for sys.settrace and sys.setprofile.
39+
enum TraceEvent {
40+
Call,
41+
Return,
42+
}
43+
44+
impl std::fmt::Display for TraceEvent {
45+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46+
use TraceEvent::*;
47+
match self {
48+
Call => write!(f, "call"),
49+
Return => write!(f, "return"),
50+
}
51+
}
52+
}
53+
54+
impl VirtualMachine {
55+
/// Call registered trace function.
56+
#[inline]
57+
fn trace_event(&self, event: TraceEvent) -> PyResult<()> {
58+
if self.use_tracing.get() {
59+
self._trace_event_inner(event)
60+
} else {
61+
Ok(())
62+
}
63+
}
64+
fn _trace_event_inner(&self, event: TraceEvent) -> PyResult<()> {
65+
let trace_func = self.trace_func.borrow().to_owned();
66+
let profile_func = self.profile_func.borrow().to_owned();
67+
if self.is_none(&trace_func) && self.is_none(&profile_func) {
68+
return Ok(());
69+
}
70+
71+
let frame_ref = self.current_frame();
72+
if frame_ref.is_none() {
73+
return Ok(());
74+
}
75+
76+
let frame = frame_ref.unwrap().as_object().to_owned();
77+
let event = self.ctx.new_str(event.to_string()).into();
78+
let args = vec![frame, event, self.ctx.none()];
79+
80+
// temporarily disable tracing, during the call to the
81+
// tracing function itself.
82+
if !self.is_none(&trace_func) {
83+
self.use_tracing.set(false);
84+
let res = self.invoke(&trace_func, args.clone());
85+
self.use_tracing.set(true);
86+
res?;
87+
}
88+
89+
if !self.is_none(&profile_func) {
90+
self.use_tracing.set(false);
91+
let res = self.invoke(&profile_func, args);
92+
self.use_tracing.set(true);
93+
res?;
94+
}
95+
Ok(())
3296
}
3397
}

vm/src/vm/vm_object.rs

Lines changed: 7 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,6 @@ use crate::{
77
vm::VirtualMachine,
88
};
99

10-
/// Trace events for sys.settrace and sys.setprofile.
11-
enum TraceEvent {
12-
Call,
13-
Return,
14-
}
15-
16-
impl std::fmt::Display for TraceEvent {
17-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
18-
use TraceEvent::*;
19-
match self {
20-
Call => write!(f, "call"),
21-
Return => write!(f, "return"),
22-
}
23-
}
24-
}
25-
2610
/// PyObject support
2711
impl VirtualMachine {
2812
#[track_caller]
@@ -167,68 +151,19 @@ impl VirtualMachine {
167151
.invoke(args, self)
168152
}
169153

170-
fn _invoke(&self, callable: &PyObject, args: FuncArgs) -> PyResult {
154+
fn _invoke(&self, obj: &PyObject, args: FuncArgs) -> PyResult {
171155
vm_trace!("Invoke: {:?} {:?}", callable, args);
172-
let slot_call = callable.class().mro_find_map(|cls| cls.slots.call.load());
173-
match slot_call {
174-
Some(slot_call) => {
175-
self.trace_event(TraceEvent::Call)?;
176-
let result = slot_call(callable, args, self);
177-
self.trace_event(TraceEvent::Return)?;
178-
result
179-
}
180-
None => Err(self.new_type_error(format!(
156+
let Some(callable) = obj.to_callable() else {
157+
return Err(self.new_type_error(format!(
181158
"'{}' object is not callable",
182-
callable.class().name()
183-
))),
184-
}
159+
obj.class().name()
160+
)));
161+
};
162+
callable.invoke(args, self)
185163
}
186164

187165
#[inline(always)]
188166
pub fn invoke(&self, func: &impl AsObject, args: impl IntoFuncArgs) -> PyResult {
189167
self._invoke(func.as_object(), args.into_args(self))
190168
}
191-
192-
/// Call registered trace function.
193-
#[inline]
194-
fn trace_event(&self, event: TraceEvent) -> PyResult<()> {
195-
if self.use_tracing.get() {
196-
self._trace_event_inner(event)
197-
} else {
198-
Ok(())
199-
}
200-
}
201-
fn _trace_event_inner(&self, event: TraceEvent) -> PyResult<()> {
202-
let trace_func = self.trace_func.borrow().to_owned();
203-
let profile_func = self.profile_func.borrow().to_owned();
204-
if self.is_none(&trace_func) && self.is_none(&profile_func) {
205-
return Ok(());
206-
}
207-
208-
let frame_ref = self.current_frame();
209-
if frame_ref.is_none() {
210-
return Ok(());
211-
}
212-
213-
let frame = frame_ref.unwrap().as_object().to_owned();
214-
let event = self.ctx.new_str(event.to_string()).into();
215-
let args = vec![frame, event, self.ctx.none()];
216-
217-
// temporarily disable tracing, during the call to the
218-
// tracing function itself.
219-
if !self.is_none(&trace_func) {
220-
self.use_tracing.set(false);
221-
let res = self.invoke(&trace_func, args.clone());
222-
self.use_tracing.set(true);
223-
res?;
224-
}
225-
226-
if !self.is_none(&profile_func) {
227-
self.use_tracing.set(false);
228-
let res = self.invoke(&profile_func, args);
229-
self.use_tracing.set(true);
230-
res?;
231-
}
232-
Ok(())
233-
}
234169
}

0 commit comments

Comments
 (0)