Skip to content

Commit aff5c7f

Browse files
Extract callable convertions from build_method_def
1 parent a15972b commit aff5c7f

1 file changed

Lines changed: 96 additions & 77 deletions

File tree

crates/capi/src/methodobject.rs

Lines changed: 96 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -70,94 +70,27 @@ pub(crate) fn build_method_def(vm: &VirtualMachine, ml: &PyMethodDef) -> PyRef<H
7070

7171
bitflags::bitflags_match!(call_flags, {
7272
PyMethodFlags::NOARGS => {
73-
let f = unsafe { method.PyCFunction };
74-
let callable = move |mut args: FuncArgs, vm: &VirtualMachine| {
75-
let slf = take_self_arg(&mut args, flags);
76-
let slf_ptr = slf
77-
.as_ref()
78-
.map(|obj| obj.as_object().as_raw().cast_mut())
79-
.unwrap_or_default();
80-
let arg_tuple = vm.ctx.new_tuple(args.args);
81-
debug_assert!(arg_tuple.is_empty(), "Expected no arguments, but got some");
82-
let ret_ptr = unsafe { f(slf_ptr, arg_tuple.as_object().as_raw().cast_mut()) };
83-
ret_ptr_to_pyresult(vm, ret_ptr)
73+
let callable = move |args: FuncArgs, vm: &VirtualMachine| unsafe {
74+
debug_assert!(args.args.len() <= 1 && args.kwargs.is_empty(), "Expected no arguments, but got some");
75+
call_function(vm, method, flags, args)
8476
};
8577
vm.ctx.new_method_def(name, callable, flags, doc)
8678
},
8779
PyMethodFlags::VARARGS => {
88-
let f = unsafe { method.PyCFunction };
89-
let callable = move |mut args: FuncArgs, vm: &VirtualMachine| {
90-
let slf = take_self_arg(&mut args, flags);
91-
let slf_ptr = slf
92-
.as_ref()
93-
.map(|obj| obj.as_object().as_raw().cast_mut())
94-
.unwrap_or_default();
95-
let arg_tuple = vm.ctx.new_tuple(args.args);
96-
let ret_ptr = unsafe { f(slf_ptr, arg_tuple.as_object().as_raw().cast_mut()) };
97-
ret_ptr_to_pyresult(vm, ret_ptr)
80+
let callable = move |args: FuncArgs, vm: &VirtualMachine| unsafe {
81+
call_function(vm, method, flags, args)
9882
};
9983
vm.ctx.new_method_def(name, callable, flags, doc)
10084
},
10185
PyMethodFlags::VARARGS | PyMethodFlags::KEYWORDS => {
102-
let f = unsafe { method.PyCFunctionWithKeywords };
103-
let callable = move |mut args: FuncArgs, vm: &VirtualMachine| {
104-
let slf = take_self_arg(&mut args, flags);
105-
let slf_ptr = slf
106-
.as_ref()
107-
.map(|obj| obj.as_object().as_raw().cast_mut())
108-
.unwrap_or_default();
109-
let arg_tuple = vm.ctx.new_tuple(args.args);
110-
let kwargs = vm.ctx.new_dict();
111-
for (k, v) in args.kwargs {
112-
kwargs.set_item(&*k, v, vm)?;
113-
}
114-
let ret_ptr = unsafe {
115-
f(
116-
slf_ptr,
117-
arg_tuple.as_object().as_raw().cast_mut(),
118-
kwargs.as_object().as_raw().cast_mut(),
119-
)
120-
};
121-
ret_ptr_to_pyresult(vm, ret_ptr)
86+
let callable = move | args: FuncArgs, vm: &VirtualMachine| unsafe {
87+
call_function_with_keywords(vm, method, flags, args)
12288
};
12389
vm.ctx.new_method_def(name, callable, flags, doc)
12490
},
12591
PyMethodFlags::FASTCALL | PyMethodFlags::KEYWORDS => {
126-
let f = unsafe { method.PyCFunctionFastWithKeywords };
127-
let callable = move |mut args: FuncArgs, vm: &VirtualMachine| {
128-
let slf = take_self_arg(&mut args, flags);
129-
let slf_ptr = slf
130-
.as_ref()
131-
.map(|obj| obj.as_object().as_raw().cast_mut())
132-
.unwrap_or_default();
133-
let nargs = args.args.len();
134-
let mut fastcall_args = args.args;
135-
let mut kwnames_tuple = None;
136-
if !args.kwargs.is_empty() {
137-
let mut kwnames = Vec::with_capacity(args.kwargs.len());
138-
for (k, v) in args.kwargs {
139-
kwnames.push(vm.ctx.new_str(k).into());
140-
fastcall_args.push(v);
141-
}
142-
kwnames_tuple = Some(vm.ctx.new_tuple(kwnames));
143-
}
144-
let fastcall_arg_ptrs = fastcall_args
145-
.iter()
146-
.map(|obj| obj.as_object().as_raw().cast_mut())
147-
.collect::<Vec<_>>();
148-
let kwnames_ptr = kwnames_tuple
149-
.as_ref()
150-
.map(|tuple| tuple.as_object().as_raw().cast_mut())
151-
.unwrap_or(core::ptr::null_mut());
152-
let ret_ptr = unsafe {
153-
f(
154-
slf_ptr,
155-
fastcall_arg_ptrs.as_ptr(),
156-
nargs as isize,
157-
kwnames_ptr,
158-
)
159-
};
160-
ret_ptr_to_pyresult(vm, ret_ptr)
92+
let callable = move |args: FuncArgs, vm: &VirtualMachine| unsafe {
93+
call_fast_function_with_keywords(vm, method, flags, args)
16194
};
16295
vm.ctx.new_method_def(name, callable, flags, doc)
16396
},
@@ -176,11 +109,97 @@ pub(crate) fn build_method_def(vm: &VirtualMachine, ml: &PyMethodDef) -> PyRef<H
176109
vm.ctx.new_method_def(name, callable, flags, doc)
177110
},
178111
_ => {
179-
todo!("unsupported or invalid calling-convention flags")
112+
todo!("function {name} has unsupported or invalid calling-convention flags: {flags:?}")
180113
},
181114
})
182115
}
183116

117+
unsafe fn call_function(
118+
vm: &VirtualMachine,
119+
method: PyMethodPointer,
120+
flags: PyMethodFlags,
121+
mut args: FuncArgs,
122+
) -> PyResult {
123+
let f = unsafe { method.PyCFunction };
124+
let slf = take_self_arg(&mut args, flags);
125+
let slf_ptr = slf
126+
.as_ref()
127+
.map(|obj| obj.as_object().as_raw().cast_mut())
128+
.unwrap_or_default();
129+
let arg_tuple = vm.ctx.new_tuple(args.args);
130+
let ret_ptr = unsafe { f(slf_ptr, arg_tuple.as_object().as_raw().cast_mut()) };
131+
ret_ptr_to_pyresult(vm, ret_ptr)
132+
}
133+
134+
unsafe fn call_function_with_keywords(
135+
vm: &VirtualMachine,
136+
method: PyMethodPointer,
137+
flags: PyMethodFlags,
138+
mut args: FuncArgs,
139+
) -> PyResult {
140+
let f = unsafe { method.PyCFunctionWithKeywords };
141+
let slf = take_self_arg(&mut args, flags);
142+
let slf_ptr = slf
143+
.as_ref()
144+
.map(|obj| obj.as_object().as_raw().cast_mut())
145+
.unwrap_or_default();
146+
let arg_tuple = vm.ctx.new_tuple(args.args);
147+
let kwargs = vm.ctx.new_dict();
148+
for (k, v) in args.kwargs {
149+
kwargs.set_item(&*k, v, vm)?;
150+
}
151+
let ret_ptr = unsafe {
152+
f(
153+
slf_ptr,
154+
arg_tuple.as_object().as_raw().cast_mut(),
155+
kwargs.as_object().as_raw().cast_mut(),
156+
)
157+
};
158+
ret_ptr_to_pyresult(vm, ret_ptr)
159+
}
160+
161+
unsafe fn call_fast_function_with_keywords(
162+
vm: &VirtualMachine,
163+
method: PyMethodPointer,
164+
flags: PyMethodFlags,
165+
mut args: FuncArgs,
166+
) -> PyResult {
167+
let f = unsafe { method.PyCFunctionFastWithKeywords };
168+
let slf = take_self_arg(&mut args, flags);
169+
let slf_ptr = slf
170+
.as_ref()
171+
.map(|obj| obj.as_object().as_raw().cast_mut())
172+
.unwrap_or_default();
173+
let nargs = args.args.len();
174+
let mut fastcall_args = args.args;
175+
let mut kwnames_tuple = None;
176+
if !args.kwargs.is_empty() {
177+
let mut kwnames = Vec::with_capacity(args.kwargs.len());
178+
for (k, v) in args.kwargs {
179+
kwnames.push(vm.ctx.new_str(k).into());
180+
fastcall_args.push(v);
181+
}
182+
kwnames_tuple = Some(vm.ctx.new_tuple(kwnames));
183+
}
184+
let fastcall_arg_ptrs = fastcall_args
185+
.iter()
186+
.map(|obj| obj.as_object().as_raw().cast_mut())
187+
.collect::<Vec<_>>();
188+
let kwnames_ptr = kwnames_tuple
189+
.as_ref()
190+
.map(|tuple| tuple.as_object().as_raw().cast_mut())
191+
.unwrap_or(core::ptr::null_mut());
192+
let ret_ptr = unsafe {
193+
f(
194+
slf_ptr,
195+
fastcall_arg_ptrs.as_ptr(),
196+
nargs as isize,
197+
kwnames_ptr,
198+
)
199+
};
200+
ret_ptr_to_pyresult(vm, ret_ptr)
201+
}
202+
184203
fn ret_ptr_to_pyresult(vm: &VirtualMachine, ret_ptr: *mut PyObject) -> PyResult {
185204
let ret_ptr = NonNull::new(ret_ptr).ok_or_else(|| {
186205
vm.take_raised_exception()

0 commit comments

Comments
 (0)