Skip to content

Commit eba367d

Browse files
Avoid creating extra args vec in fastcall functions
1 parent 4c7144e commit eba367d

1 file changed

Lines changed: 12 additions & 14 deletions

File tree

crates/capi/src/methodobject.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub union PyMethodPointer {
3030
) -> *mut PyObject,
3131
pub PyCFunctionFast: unsafe extern "C" fn(
3232
slf: *mut PyObject,
33-
args: *mut *mut PyObject,
33+
args: *const *mut PyObject,
3434
nargs: isize,
3535
) -> *mut PyObject,
3636
pub PyCFunctionFastWithKeywords: unsafe extern "C" fn(
@@ -216,18 +216,18 @@ unsafe fn call_fast_function_with_keywords(
216216
} else {
217217
None
218218
};
219-
let fastcall_arg_ptrs = fastcall_args
220-
.iter()
221-
.map(|obj| obj.as_object().as_raw().cast_mut())
222-
.collect::<Vec<_>>();
223219
let kwnames_ptr = kwnames_tuple
224220
.as_ref()
225221
.map(|tuple| tuple.as_object().as_raw().cast_mut())
226222
.unwrap_or_default();
223+
// SAFETY: PyObjectRef is repr(transparent) over a pointer to PyObject, so a
224+
// Vec<PyObjectRef> has a layout-compatible contiguous backing buffer. The
225+
// vector is kept alive for the duration of the call.
226+
let fastcall_arg_ptrs = fastcall_args.as_ptr().cast::<*mut PyObject>();
227227
let ret_ptr = unsafe {
228228
f(
229229
slf_ptr,
230-
fastcall_arg_ptrs.as_ptr(),
230+
fastcall_arg_ptrs,
231231
nargs as isize,
232232
kwnames_ptr,
233233
)
@@ -248,17 +248,15 @@ unsafe fn call_fast_function(
248248
.as_ref()
249249
.map(|obj| obj.as_object().as_raw().cast_mut())
250250
.unwrap_or_default();
251-
// TODO can we avoid creating a new vec here?
252-
let mut fastcall_arg_ptrs = args
253-
.args
254-
.iter()
255-
.map(|obj| obj.as_object().as_raw().cast_mut())
256-
.collect::<Vec<_>>();
251+
// SAFETY: PyObjectRef is repr(transparent) over a pointer to PyObject, so a
252+
// Vec<PyObjectRef> has a layout-compatible contiguous backing buffer. The
253+
// vector is kept alive for the duration of the call.
254+
let fastcall_arg_ptrs = args.args.as_mut_ptr().cast::<*mut PyObject>();
257255
let ret_ptr = unsafe {
258256
f(
259257
slf_ptr,
260-
fastcall_arg_ptrs.as_mut_ptr(),
261-
fastcall_arg_ptrs.len() as isize,
258+
fastcall_arg_ptrs,
259+
args.args.len() as isize,
262260
)
263261
};
264262
ret_ptr_to_pyresult(vm, ret_ptr)

0 commit comments

Comments
 (0)