Skip to content

Commit 1166a99

Browse files
alexdavidhewitt
authored andcommitted
Refactor create_type_object so that most of the code is monomorphic
In pyca/cryptography this function is the #1 source of lines of generated LLVM IR, because it is duplicated 42x (and growing!). By rewriting it so most of the logic is monomorphic, we reduce the generated LLVM IR for this function by 4x.
1 parent 856b859 commit 1166a99

File tree

1 file changed

+47
-11
lines changed

1 file changed

+47
-11
lines changed

src/pyclass/create_type_object.rs

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,34 @@ pub(crate) fn create_type_object<T>(py: Python<'_>) -> PyResult<PyClassTypeObjec
3333
where
3434
T: PyClass,
3535
{
36-
unsafe {
36+
// Written this way to monomorphize the majority of the logic.
37+
#[allow(clippy::too_many_arguments)]
38+
unsafe fn inner(
39+
py: Python<'_>,
40+
base: *mut ffi::PyTypeObject,
41+
dealloc: unsafe extern "C" fn(*mut ffi::PyObject),
42+
dealloc_with_gc: unsafe extern "C" fn(*mut ffi::PyObject),
43+
is_mapping: bool,
44+
is_sequence: bool,
45+
doc: &'static CStr,
46+
dict_offset: Option<ffi::Py_ssize_t>,
47+
weaklist_offset: Option<ffi::Py_ssize_t>,
48+
is_basetype: bool,
49+
items_iter: PyClassItemsIter,
50+
name: &'static str,
51+
module: Option<&'static str>,
52+
size_of: usize,
53+
) -> PyResult<PyClassTypeObject> {
3754
PyTypeBuilder {
3855
slots: Vec::new(),
3956
method_defs: Vec::new(),
4057
getset_builders: HashMap::new(),
4158
cleanup: Vec::new(),
42-
tp_base: T::BaseType::type_object_raw(py),
43-
tp_dealloc: tp_dealloc::<T>,
44-
tp_dealloc_with_gc: tp_dealloc_with_gc::<T>,
45-
is_mapping: T::IS_MAPPING,
46-
is_sequence: T::IS_SEQUENCE,
59+
tp_base: base,
60+
tp_dealloc: dealloc,
61+
tp_dealloc_with_gc: dealloc_with_gc,
62+
is_mapping,
63+
is_sequence,
4764
has_new: false,
4865
has_dealloc: false,
4966
has_getitem: false,
@@ -55,11 +72,30 @@ where
5572
#[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))]
5673
buffer_procs: Default::default(),
5774
}
58-
.type_doc(T::doc(py)?)
59-
.offsets(T::dict_offset(), T::weaklist_offset())
60-
.set_is_basetype(T::IS_BASETYPE)
61-
.class_items(T::items_iter())
62-
.build(py, T::NAME, T::MODULE, std::mem::size_of::<PyCell<T>>())
75+
.type_doc(doc)
76+
.offsets(dict_offset, weaklist_offset)
77+
.set_is_basetype(is_basetype)
78+
.class_items(items_iter)
79+
.build(py, name, module, size_of)
80+
}
81+
82+
unsafe {
83+
inner(
84+
py,
85+
T::BaseType::type_object_raw(py),
86+
tp_dealloc::<T>,
87+
tp_dealloc_with_gc::<T>,
88+
T::IS_MAPPING,
89+
T::IS_SEQUENCE,
90+
T::doc(py)?,
91+
T::dict_offset(),
92+
T::weaklist_offset(),
93+
T::IS_BASETYPE,
94+
T::items_iter(),
95+
T::NAME,
96+
T::MODULE,
97+
std::mem::size_of::<PyCell<T>>(),
98+
)
6399
}
64100
}
65101

0 commit comments

Comments
 (0)