From 50d15285d850ad6e48179695d5995751d852aedf Mon Sep 17 00:00:00 2001 From: Josh taylor Date: Sun, 10 Jul 2022 09:23:35 +0800 Subject: [PATCH] Add inline --- rustler/src/env.rs | 4 ++++ rustler/src/term.rs | 6 ++++++ rustler/src/types/binary.rs | 14 ++++++++++++++ rustler/src/types/list.rs | 11 +++++++++++ rustler/src/types/local_pid.rs | 5 +++++ rustler/src/types/map.rs | 9 +++++++++ rustler/src/types/primitive.rs | 2 ++ rustler/src/types/string.rs | 2 ++ rustler/src/wrapper/list.rs | 5 +++++ rustler/src/wrapper/map.rs | 2 ++ rustler_codegen/src/context.rs | 16 ++++++++++++++++ rustler_codegen/src/ex_struct.rs | 1 + rustler_codegen/src/lib.rs | 1 + 13 files changed, 78 insertions(+) diff --git a/rustler/src/env.rs b/rustler/src/env.rs index a1bf3c49..c8bb0d70 100644 --- a/rustler/src/env.rs +++ b/rustler/src/env.rs @@ -40,6 +40,7 @@ impl<'a> Env<'a> { /// /// # Unsafe /// Don't create multiple `Env`s with the same lifetime. + #[inline] pub unsafe fn new(_lifetime_marker: &'a T, env: NIF_ENV) -> Env<'a> { Env { env, @@ -47,11 +48,13 @@ impl<'a> Env<'a> { } } + #[inline] pub fn as_c_arg(self) -> NIF_ENV { self.env } /// Convenience method for building a tuple `{error, Reason}`. + #[inline] pub fn error_tuple(self, reason: T) -> Term<'a> where T: Encoder, @@ -76,6 +79,7 @@ impl<'a> Env<'a> { /// Panics if the above rules are broken (by trying to send a message from /// an `OwnedEnv` on a thread that's managed by the Erlang VM). /// + #[inline] pub fn send(self, pid: &LocalPid, message: Term<'a>) { let thread_type = unsafe { rustler_sys::enif_thread_type() }; let env = if thread_type == rustler_sys::ERL_NIF_THR_UNDEFINED { diff --git a/rustler/src/term.rs b/rustler/src/term.rs index d9a3e149..fec54b5e 100644 --- a/rustler/src/term.rs +++ b/rustler/src/term.rs @@ -28,15 +28,18 @@ impl<'a> Term<'a> { /// # Unsafe /// The caller must ensure that `env` is the environment that `inner` belongs to, /// unless `inner` is an atom term. + #[inline] pub unsafe fn new(env: Env<'a>, inner: NIF_TERM) -> Self { Term { term: inner, env } } /// This extracts the raw term pointer. It is usually used in order to obtain a type that can /// be passed to calls into the erlang vm. + #[inline] pub fn as_c_arg(&self) -> NIF_TERM { self.term } + #[inline] pub fn get_env(&self) -> Env<'a> { self.env } @@ -45,6 +48,7 @@ impl<'a> Term<'a> { /// /// If the term is already is in the provided env, it will be directly returned. Otherwise /// the term will be copied over. + #[inline] pub fn in_env<'b>(&self, env: Env<'b>) -> Term<'b> { if self.get_env() == env { // It's safe to create a new Term<'b> without copying because we @@ -85,6 +89,7 @@ impl<'a> Term<'a> { /// is needed. /// /// [`decode`]: #method.decode + #[inline] pub fn decode_as_binary(self) -> NifResult> { if self.is_binary() { return Binary::from_term(self); @@ -92,6 +97,7 @@ impl<'a> Term<'a> { Binary::from_iolist(self) } + #[inline] pub fn to_binary(self) -> OwnedBinary { let raw_binary = unsafe { term_to_binary(self.env.as_c_arg(), self.as_c_arg()) }.unwrap(); unsafe { OwnedBinary::from_raw(raw_binary) } diff --git a/rustler/src/types/binary.rs b/rustler/src/types/binary.rs index d18916f0..0e40124e 100644 --- a/rustler/src/types/binary.rs +++ b/rustler/src/types/binary.rs @@ -242,6 +242,7 @@ pub struct Binary<'a> { impl<'a> Binary<'a> { /// Consumes `owned` and returns an immutable `Binary`. + #[inline] pub fn from_owned(owned: OwnedBinary, env: Env<'a>) -> Self { // We are transferring ownership of `owned`'s data to the // environment. Therefore, we need to prevent `owned`'s destructor being @@ -267,6 +268,7 @@ impl<'a> Binary<'a> { /// /// If allocation fails, an error will be returned. #[allow(clippy::wrong_self_convention)] + #[inline] pub fn to_owned(&self) -> Option { OwnedBinary::from_unowned(self) } @@ -276,6 +278,7 @@ impl<'a> Binary<'a> { /// # Errors /// /// If `term` is not a binary, an error will be returned. + #[inline] pub fn from_term(term: Term<'a>) -> Result { let mut binary = MaybeUninit::uninit(); if unsafe { @@ -299,6 +302,7 @@ impl<'a> Binary<'a> { /// # Errors /// /// If `term` is not an `iolist`, an error will be returned. + #[inline] pub fn from_iolist(term: Term<'a>) -> Result { let mut binary = MaybeUninit::uninit(); if unsafe { @@ -319,11 +323,13 @@ impl<'a> Binary<'a> { /// Returns an Erlang term representation of `self`. #[allow(clippy::wrong_self_convention)] + #[inline] pub fn to_term<'b>(&self, env: Env<'b>) -> Term<'b> { self.term.in_env(env) } /// Extracts a slice containing the entire binary. + #[inline] pub fn as_slice(&self) -> &'a [u8] { unsafe { ::std::slice::from_raw_parts(self.inner.data, self.inner.size) } } @@ -336,6 +342,7 @@ impl<'a> Binary<'a> { /// # Errors /// /// If `offset + length` is out of bounds, an error will be returned. + #[inline] pub fn make_subbinary(&self, offset: usize, length: usize) -> NifResult> { let min_len = length.checked_add(offset); if min_len.ok_or(Error::BadArg)? > self.inner.size { @@ -415,28 +422,33 @@ pub struct NewBinary<'a> { impl<'a> NewBinary<'a> { /// Allocates a new `NewBinary` + #[inline] pub fn new(env: Env<'a>, size: usize) -> Self { let (buf, term) = unsafe { new_binary(env, size) }; NewBinary { buf, term, size } } /// Extracts a slice containing the entire binary. + #[inline] pub fn as_slice(&self) -> &[u8] { unsafe { ::std::slice::from_raw_parts(self.buf, self.size) } } /// Extracts a mutable slice of the entire binary. + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { ::std::slice::from_raw_parts_mut(self.buf, self.size) } } } impl<'a> From> for Binary<'a> { + #[inline] fn from(new_binary: NewBinary<'a>) -> Self { Binary::from_term(new_binary.term).unwrap() } } impl<'a> From> for Term<'a> { + #[inline] fn from(new_binary: NewBinary<'a>) -> Self { new_binary.term } @@ -444,11 +456,13 @@ impl<'a> From> for Term<'a> { impl<'a> Deref for NewBinary<'a> { type Target = [u8]; + #[inline] fn deref(&self) -> &[u8] { self.as_slice() } } impl<'a> DerefMut for NewBinary<'a> { + #[inline] fn deref_mut(&mut self) -> &mut [u8] { self.as_mut_slice() } diff --git a/rustler/src/types/list.rs b/rustler/src/types/list.rs index 1bdc3db2..af1412fd 100644 --- a/rustler/src/types/list.rs +++ b/rustler/src/types/list.rs @@ -56,6 +56,7 @@ impl<'a> ListIterator<'a> { impl<'a> Iterator for ListIterator<'a> { type Item = Term<'a>; + #[inline] fn next(&mut self) -> Option> { let env = self.term.get_env(); let cell = unsafe { list::get_list_cell(env.as_c_arg(), self.term.as_c_arg()) }; @@ -78,6 +79,7 @@ impl<'a> Iterator for ListIterator<'a> { } impl<'a> Decoder<'a> for ListIterator<'a> { + #[inline] fn decode(term: Term<'a>) -> NifResult { match ListIterator::new(term) { Some(iter) => Ok(iter), @@ -97,6 +99,7 @@ impl<'a, T> Encoder for Vec where T: Encoder, { + #[inline] fn encode<'b>(&self, env: Env<'b>) -> Term<'b> { self.as_slice().encode(env) } @@ -106,6 +109,7 @@ impl<'a, T> Decoder<'a> for Vec where T: Decoder<'a>, { + #[inline] fn decode(term: Term<'a>) -> NifResult { let iter: ListIterator = term.decode()?; let res: NifResult = iter.map(|x| x.decode::()).collect(); @@ -117,6 +121,7 @@ impl<'a, T> Encoder for [T] where T: Encoder, { + #[inline] fn encode<'b>(&self, env: Env<'b>) -> Term<'b> { let term_array: Vec = self.iter().map(|x| x.encode(env).as_c_arg()).collect(); unsafe { Term::new(env, list::make_list(env.as_c_arg(), &term_array)) } @@ -126,6 +131,7 @@ impl<'a, T> Encoder for &'a [T] where T: Encoder, { + #[inline] fn encode<'b>(&self, env: Env<'b>) -> Term<'b> { let term_array: Vec = self.iter().map(|x| x.encode(env).as_c_arg()).collect(); unsafe { Term::new(env, list::make_list(env.as_c_arg(), &term_array)) } @@ -135,6 +141,7 @@ where /// ## List terms impl<'a> Term<'a> { /// Returns a new empty list. + #[inline] pub fn list_new_empty(env: Env<'a>) -> Term<'a> { let list: &[u8] = &[]; list.encode(env) @@ -144,6 +151,7 @@ impl<'a> Term<'a> { /// See documentation for ListIterator for more information. /// /// Returns None if the term is not a list. + #[inline] pub fn into_list_iterator(self) -> NifResult> { ListIterator::new(self).ok_or(Error::BadArg) } @@ -156,6 +164,7 @@ impl<'a> Term<'a> { /// ```elixir /// length(self_term) /// ``` + #[inline] pub fn list_length(self) -> NifResult { unsafe { list::get_list_length(self.get_env().as_c_arg(), self.as_c_arg()) } .ok_or(Error::BadArg) @@ -171,6 +180,7 @@ impl<'a> Term<'a> { /// [head, tail] = self_term /// {head, tail} /// ``` + #[inline] pub fn list_get_cell(self) -> NifResult<(Term<'a>, Term<'a>)> { let env = self.get_env(); unsafe { @@ -183,6 +193,7 @@ impl<'a> Term<'a> { /// Makes a copy of the self list term and reverses it. /// /// Returns Err(Error::BadArg) if the term is not a list. + #[inline] pub fn list_reverse(self) -> NifResult> { let env = self.get_env(); unsafe { diff --git a/rustler/src/types/local_pid.rs b/rustler/src/types/local_pid.rs index 437569ae..526de398 100644 --- a/rustler/src/types/local_pid.rs +++ b/rustler/src/types/local_pid.rs @@ -8,16 +8,19 @@ pub struct LocalPid { } impl LocalPid { + #[inline] pub fn as_c_arg(&self) -> &ErlNifPid { &self.c } + #[inline] pub fn from_c_arg(erl_nif_pid: ErlNifPid) -> Self { LocalPid { c: erl_nif_pid } } } impl<'a> Decoder<'a> for LocalPid { + #[inline] fn decode(term: Term<'a>) -> NifResult { unsafe { pid::get_local_pid(term.get_env().as_c_arg(), term.as_c_arg()) } .map(|pid| LocalPid { c: pid }) @@ -26,6 +29,7 @@ impl<'a> Decoder<'a> for LocalPid { } impl Encoder for LocalPid { + #[inline] fn encode<'a>(&self, env: Env<'a>) -> Term<'a> { unsafe { Term::new(env, pid::make_pid(env.as_c_arg(), self.c)) } } @@ -39,6 +43,7 @@ impl<'a> Env<'a> { /// Panics if this environment is process-independent. (The only way to get such an /// environment is to use `OwnedEnv`. The `Env` that Rustler passes to NIFs when they're /// called is always associated with the calling Erlang process.) + #[inline] pub fn pid(self) -> LocalPid { let mut pid = MaybeUninit::uninit(); if unsafe { rustler_sys::enif_self(self.as_c_arg(), pid.as_mut_ptr()) }.is_null() { diff --git a/rustler/src/types/map.rs b/rustler/src/types/map.rs index e3ea5764..c12ef4fa 100644 --- a/rustler/src/types/map.rs +++ b/rustler/src/types/map.rs @@ -5,6 +5,7 @@ use crate::wrapper::map; use crate::{Decoder, Encoder, Env, Error, NifResult, Term}; use std::ops::RangeInclusive; +#[inline] pub fn map_new(env: Env) -> Term { unsafe { Term::new(env, map::map_new(env.as_c_arg())) } } @@ -17,6 +18,7 @@ impl<'a> Term<'a> { /// ```elixir /// %{} /// ``` + #[inline] pub fn map_new(env: Env<'a>) -> Term<'a> { map_new(env) } @@ -29,6 +31,7 @@ impl<'a> Term<'a> { /// values = [1, 2] /// List.zip(keys, values) |> Map.new() /// ``` + #[inline] pub fn map_from_arrays( env: Env<'a>, keys: &[impl Encoder], @@ -57,6 +60,7 @@ impl<'a> Term<'a> { /// ```elixir /// Map.new([{"foo", 1}, {"bar", 2}]) /// ``` + #[inline] pub fn map_from_pairs( env: Env<'a>, pairs: &[(impl Encoder, impl Encoder)], @@ -81,6 +85,7 @@ impl<'a> Term<'a> { /// ```elixir /// Map.get(self_term, key) /// ``` + #[inline] pub fn map_get(self, key: impl Encoder) -> NifResult> { let env = self.get_env(); match unsafe { @@ -99,6 +104,7 @@ impl<'a> Term<'a> { /// ```elixir /// map_size(self_term) /// ``` + #[inline] pub fn map_size(self) -> NifResult { let env = self.get_env(); unsafe { map::get_map_size(env.as_c_arg(), self.as_c_arg()).ok_or(Error::BadArg) } @@ -113,6 +119,7 @@ impl<'a> Term<'a> { /// ```elixir /// Map.put(self_term, key, value) /// ``` + #[inline] pub fn map_put(self, key: impl Encoder, value: impl Encoder) -> NifResult> { let env = self.get_env(); @@ -138,6 +145,7 @@ impl<'a> Term<'a> { /// ```elixir /// Map.delete(self_term, key) /// ``` + #[inline] pub fn map_remove(self, key: impl Encoder) -> NifResult> { let env = self.get_env(); @@ -153,6 +161,7 @@ impl<'a> Term<'a> { /// /// Returns Err(Error::BadArg) if the term is not a map of if key /// doesn't exist. + #[inline] pub fn map_update(self, key: impl Encoder, new_value: impl Encoder) -> NifResult> { let env = self.get_env(); diff --git a/rustler/src/types/primitive.rs b/rustler/src/types/primitive.rs index f501b504..c7050a8a 100644 --- a/rustler/src/types/primitive.rs +++ b/rustler/src/types/primitive.rs @@ -4,6 +4,7 @@ use crate::{Decoder, Encoder, Env, Error, NifResult, Term}; macro_rules! impl_number_transcoder { ($dec_type:ty, $nif_type:ty, $encode_fun:ident, $decode_fun:ident) => { impl Encoder for $dec_type { + #[inline] fn encode<'a>(&self, env: Env<'a>) -> Term<'a> { #[allow(clippy::cast_lossless)] unsafe { @@ -15,6 +16,7 @@ macro_rules! impl_number_transcoder { } } impl<'a> Decoder<'a> for $dec_type { + #[inline] fn decode(term: Term) -> NifResult<$dec_type> { #![allow(unused_unsafe)] let mut res: $nif_type = Default::default(); diff --git a/rustler/src/types/string.rs b/rustler/src/types/string.rs index 4833bd2c..97311923 100644 --- a/rustler/src/types/string.rs +++ b/rustler/src/types/string.rs @@ -2,12 +2,14 @@ use super::binary::{Binary, OwnedBinary}; use crate::{Decoder, Encoder, Env, Error, NifResult, Term}; impl<'a> Decoder<'a> for String { + #[inline] fn decode(term: Term<'a>) -> NifResult { let string: &str = Decoder::decode(term)?; Ok(string.to_string()) } } impl<'a> Decoder<'a> for &'a str { + #[inline] fn decode(term: Term<'a>) -> NifResult { let binary = Binary::from_term(term)?; match ::std::str::from_utf8(binary.as_slice()) { diff --git a/rustler/src/wrapper/list.rs b/rustler/src/wrapper/list.rs index af62a47e..a12c8031 100644 --- a/rustler/src/wrapper/list.rs +++ b/rustler/src/wrapper/list.rs @@ -1,6 +1,7 @@ use crate::wrapper::{NIF_ENV, NIF_TERM}; use std::mem::MaybeUninit; +#[inline] pub unsafe fn get_list_cell(env: NIF_ENV, list: NIF_TERM) -> Option<(NIF_TERM, NIF_TERM)> { let mut head = MaybeUninit::uninit(); let mut tail = MaybeUninit::uninit(); @@ -12,6 +13,7 @@ pub unsafe fn get_list_cell(env: NIF_ENV, list: NIF_TERM) -> Option<(NIF_TERM, N Some((head.assume_init(), tail.assume_init())) } +#[inline] pub unsafe fn get_list_length(env: NIF_ENV, list: NIF_TERM) -> Option { let mut len: u32 = 0; let success = rustler_sys::enif_get_list_length(env, list, &mut len); @@ -22,14 +24,17 @@ pub unsafe fn get_list_length(env: NIF_ENV, list: NIF_TERM) -> Option { Some(len as usize) } +#[inline] pub unsafe fn make_list(env: NIF_ENV, arr: &[NIF_TERM]) -> NIF_TERM { rustler_sys::enif_make_list_from_array(env, arr.as_ptr(), arr.len() as u32) } +#[inline] pub unsafe fn make_list_cell(env: NIF_ENV, head: NIF_TERM, tail: NIF_TERM) -> NIF_TERM { rustler_sys::enif_make_list_cell(env, head, tail) } +#[inline] pub unsafe fn make_reverse_list(env: NIF_ENV, list: NIF_TERM) -> Option { let mut list_out = MaybeUninit::uninit(); let success = rustler_sys::enif_make_reverse_list(env, list, list_out.as_mut_ptr()); diff --git a/rustler/src/wrapper/map.rs b/rustler/src/wrapper/map.rs index a9ca0be0..9ae5ef4a 100644 --- a/rustler/src/wrapper/map.rs +++ b/rustler/src/wrapper/map.rs @@ -99,10 +99,12 @@ pub unsafe fn map_iterator_get_pair( } } +#[inline] pub unsafe fn map_iterator_next(env: NIF_ENV, iter: &mut ErlNifMapIterator) { rustler_sys::enif_map_iterator_next(env, iter); } +#[inline] pub unsafe fn make_map_from_arrays( env: NIF_ENV, keys: &[NIF_TERM], diff --git a/rustler_codegen/src/context.rs b/rustler_codegen/src/context.rs index 9ac59e64..3d981671 100644 --- a/rustler_codegen/src/context.rs +++ b/rustler_codegen/src/context.rs @@ -23,6 +23,7 @@ pub(crate) struct Context<'a> { } impl<'a> Context<'a> { + #[inline] pub fn from_ast(ast: &'a syn::DeriveInput) -> Self { let mut attrs: Vec<_> = ast .attrs @@ -79,10 +80,12 @@ impl<'a> Context<'a> { } } + #[inline] pub fn atoms_module_name(&self, span: Span) -> Ident { Ident::new(&format!("RUSTLER_ATOMS_{}", self.ident), span) } + #[inline] pub fn encode(&self) -> bool { self.attrs.iter().any(|attr| match attr { RustlerAttr::Encode => true, @@ -90,6 +93,7 @@ impl<'a> Context<'a> { }) } + #[inline] pub fn decode(&self) -> bool { self.attrs.iter().any(|attr| match attr { RustlerAttr::Decode => true, @@ -97,6 +101,7 @@ impl<'a> Context<'a> { }) } + #[inline] pub fn field_atoms(&self) -> Option> { self.struct_fields.as_ref().map(|struct_fields| { struct_fields @@ -116,11 +121,13 @@ impl<'a> Context<'a> { }) } + #[inline] pub fn field_to_atom_fun(field: &Field) -> Ident { let ident = field.ident.as_ref().unwrap(); Self::ident_to_atom_fun(ident) } + #[inline] pub fn ident_to_atom_fun(ident: &Ident) -> Ident { let ident_str = ident.to_string().to_snake_case(); let ident_str = Self::remove_raw(&ident_str); @@ -128,6 +135,7 @@ impl<'a> Context<'a> { Ident::new(&format!("atom_{}", ident_str), Span::call_site()) } + #[inline] pub fn escape_ident_with_index(ident_str: &str, index: usize, infix: &str) -> Ident { Ident::new( &format!( @@ -140,6 +148,7 @@ impl<'a> Context<'a> { ) } + #[inline] pub fn escape_ident(ident_str: &str, infix: &str) -> Ident { Ident::new( &format!("rustler_{}_field_{}", infix, Self::remove_raw(ident_str)), @@ -147,6 +156,7 @@ impl<'a> Context<'a> { ) } + #[inline] fn remove_raw(ident_str: &str) -> &str { ident_str .split("r#") @@ -154,6 +164,7 @@ impl<'a> Context<'a> { .expect("split has always at least one element") } + #[inline] fn encode_decode_attr_set(attrs: &[RustlerAttr]) -> bool { attrs.iter().any(|attr| match attr { RustlerAttr::Encode => true, @@ -162,6 +173,7 @@ impl<'a> Context<'a> { }) } + #[inline] fn get_rustler_attrs(attr: &syn::Attribute) -> Vec { attr.path .segments @@ -179,6 +191,7 @@ impl<'a> Context<'a> { .collect() } + #[inline] fn parse_rustler(meta: &Meta) -> Vec { if let Meta::List(ref list) = meta { return list @@ -191,6 +204,7 @@ impl<'a> Context<'a> { panic!("Expected encode and/or decode in rustler attribute"); } + #[inline] fn parse_nested_rustler(nested: &NestedMeta) -> RustlerAttr { if let NestedMeta::Meta(Meta::Path(ref path)) = nested { match path.segments[0].ident.to_string().as_ref() { @@ -203,6 +217,7 @@ impl<'a> Context<'a> { panic!("Expected encode and/or decode in rustler attribute"); } + #[inline] fn try_parse_tag(meta: &Meta) -> Option> { if let Meta::NameValue(ref name_value) = meta { if let Lit::Str(ref tag) = name_value.lit { @@ -212,6 +227,7 @@ impl<'a> Context<'a> { panic!("Cannot parse module") } + #[inline] fn try_parse_module(meta: &Meta) -> Option> { if let Meta::NameValue(name_value) = meta { if let Lit::Str(ref module) = name_value.lit { diff --git a/rustler_codegen/src/ex_struct.rs b/rustler_codegen/src/ex_struct.rs index f9a394ce..e8576068 100644 --- a/rustler_codegen/src/ex_struct.rs +++ b/rustler_codegen/src/ex_struct.rs @@ -175,6 +175,7 @@ fn gen_encoder( gen } +#[inline] fn get_module(ctx: &Context, add_exception: bool) -> String { let expect_message = if add_exception { "NifException requires a 'module' attribute" diff --git a/rustler_codegen/src/lib.rs b/rustler_codegen/src/lib.rs index b96c1143..29603998 100644 --- a/rustler_codegen/src/lib.rs +++ b/rustler_codegen/src/lib.rs @@ -118,6 +118,7 @@ pub fn nif(args: TokenStream, input: TokenStream) -> TokenStream { /// such that you can use the Elixir struct definition for it. #[proc_macro_derive(NifStruct, attributes(module, rustler))] +#[inline] pub fn nif_struct(input: TokenStream) -> TokenStream { let ast = syn::parse(input).unwrap(); ex_struct::transcoder_decorator(&ast, false).into()