mirror of
https://github.com/bspeice/qadapt
synced 2024-11-24 23:08:11 -05:00
Strip QADAPT symbols for release-mode builds
This commit is contained in:
parent
84739c4dd1
commit
af2781b453
@ -20,6 +20,31 @@ type G = proc_macro::Group;
|
|||||||
type I = proc_macro::Ident;
|
type I = proc_macro::Ident;
|
||||||
type P = proc_macro::Punct;
|
type P = proc_macro::Punct;
|
||||||
|
|
||||||
|
fn release_guard(fn_name: &str) -> TokenStream {
|
||||||
|
let rel = I::new("release", Span::call_site());
|
||||||
|
let not_rel: Vec<TokenTree> = vec![
|
||||||
|
I::new("not", Span::call_site()).into(),
|
||||||
|
G::new(Delimiter::Parenthesis, TokenTree::Ident(rel).into()).into()
|
||||||
|
];
|
||||||
|
let cfg_not_rel: Vec<TokenTree> = vec![
|
||||||
|
I::new("cfg", Span::call_site()).into(),
|
||||||
|
G::new(Delimiter::Parenthesis, TS::from_iter(not_rel.into_iter())).into()
|
||||||
|
];
|
||||||
|
let guarded: Vec<TokenTree> = vec![
|
||||||
|
P::new('#', Spacing::Alone).into(),
|
||||||
|
G::new(Delimiter::Bracket, TS::from_iter(cfg_not_rel.into_iter())).into(),
|
||||||
|
P::new(':', Spacing::Joint).into(),
|
||||||
|
P::new(':', Spacing::Alone).into(),
|
||||||
|
I::new("qadapt", Span::call_site()).into(),
|
||||||
|
P::new(':', Spacing::Joint).into(),
|
||||||
|
P::new(':', Spacing::Alone).into(),
|
||||||
|
I::new(fn_name, Span::call_site()).into(),
|
||||||
|
G::new(Delimiter::Parenthesis, TokenStream::new()).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
TS::from_iter(guarded.into_iter())
|
||||||
|
}
|
||||||
|
|
||||||
fn protected_body(fn_name: &str, args: G) -> TokenTree {
|
fn protected_body(fn_name: &str, args: G) -> TokenTree {
|
||||||
let mut args_filtered = Vec::new();
|
let mut args_filtered = Vec::new();
|
||||||
let mut waiting_for_comma = false;
|
let mut waiting_for_comma = false;
|
||||||
@ -42,28 +67,14 @@ fn protected_body(fn_name: &str, args: G) -> TokenTree {
|
|||||||
let args_group = G::new(Delimiter::Parenthesis, TS::from_iter(args_filtered));
|
let args_group = G::new(Delimiter::Parenthesis, TS::from_iter(args_filtered));
|
||||||
|
|
||||||
let tt: Vec<TT> = vec![
|
let tt: Vec<TT> = vec![
|
||||||
P::new(':', Spacing::Joint).into(),
|
G::new(Delimiter::Brace, release_guard("enter_protected")).into(),
|
||||||
P::new(':', Spacing::Alone).into(),
|
|
||||||
I::new("qadapt", Span::call_site()).into(),
|
|
||||||
P::new(':', Spacing::Joint).into(),
|
|
||||||
P::new(':', Spacing::Alone).into(),
|
|
||||||
I::new("enter_protected", Span::call_site()).into(),
|
|
||||||
G::new(Delimiter::Parenthesis, TokenStream::new()).into(),
|
|
||||||
P::new(';', Spacing::Alone).into(),
|
|
||||||
I::new("let", Span::call_site()).into(),
|
I::new("let", Span::call_site()).into(),
|
||||||
I::new("__ret__", Span::call_site()).into(),
|
I::new("__ret__", Span::call_site()).into(),
|
||||||
P::new('=', Spacing::Alone).into(),
|
P::new('=', Spacing::Alone).into(),
|
||||||
I::new(fn_name, Span::call_site()).into(),
|
I::new(fn_name, Span::call_site()).into(),
|
||||||
args_group.into(),
|
args_group.into(),
|
||||||
P::new(';', Spacing::Alone).into(),
|
P::new(';', Spacing::Alone).into(),
|
||||||
P::new(':', Spacing::Joint).into(),
|
G::new(Delimiter::Brace, release_guard("exit_protected")).into(),
|
||||||
P::new(':', Spacing::Alone).into(),
|
|
||||||
I::new("qadapt", Span::call_site()).into(),
|
|
||||||
P::new(':', Spacing::Joint).into(),
|
|
||||||
P::new(':', Spacing::Alone).into(),
|
|
||||||
I::new("exit_protected", Span::call_site()).into(),
|
|
||||||
G::new(Delimiter::Parenthesis, TokenStream::new()).into(),
|
|
||||||
P::new(';', Spacing::Alone).into(),
|
|
||||||
I::new("__ret__", Span::call_site()).into(),
|
I::new("__ret__", Span::call_site()).into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -3,12 +3,8 @@
|
|||||||
//! This allocator is a helper for writing high-performance code that is allocation/drop free;
|
//! This allocator is a helper for writing high-performance code that is allocation/drop free;
|
||||||
//! for functions annotated with `#[allocate_panic]`, QADAPT will detect when allocations/drops
|
//! for functions annotated with `#[allocate_panic]`, QADAPT will detect when allocations/drops
|
||||||
//! happen during their execution (and execution of any functions they call) and throw a
|
//! happen during their execution (and execution of any functions they call) and throw a
|
||||||
//! thread panic if this occurs.
|
//! thread panic if this occurs. QADAPT-related code is stripped out during release builds,
|
||||||
//!
|
//! so no worries about random allocations crashing in production.
|
||||||
//! Because QADAPT panics on allocation and is rather slow (for an allocator) it is **strongly**
|
|
||||||
//! recommended that QADAPT (the allocator) be used only in code tests. Functions annotated with
|
|
||||||
//! `#[allocate_panic]` will have no side effects if the QADAPT allocator is not being used,
|
|
||||||
//! so the attribute is safe to leave everywhere.
|
|
||||||
//!
|
//!
|
||||||
//! Currently this crate is Nightly-only, but will work once `const fn` is in Stable.
|
//! Currently this crate is Nightly-only, but will work once `const fn` is in Stable.
|
||||||
//!
|
//!
|
||||||
|
@ -3,6 +3,7 @@ extern crate qadapt;
|
|||||||
|
|
||||||
use qadapt::enter_protected;
|
use qadapt::enter_protected;
|
||||||
use qadapt::exit_protected;
|
use qadapt::exit_protected;
|
||||||
|
use qadapt::protection_level;
|
||||||
use qadapt::QADAPT;
|
use qadapt::QADAPT;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
@ -59,6 +60,11 @@ fn test_vec_push() {
|
|||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
enter_protected();
|
enter_protected();
|
||||||
v.push(0);
|
v.push(0);
|
||||||
|
// We don't make it here in debug mode, but in release mode,
|
||||||
|
// pushing one element doesn't trigger an allocation. Instead,
|
||||||
|
// we use a box to force it onto the heap
|
||||||
|
assert_eq!(protection_level(), 1);
|
||||||
|
let _b = Box::new(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -89,7 +95,12 @@ fn test_vec_new() {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_vec_with_one() {
|
fn test_vec_with_one() {
|
||||||
enter_protected();
|
enter_protected();
|
||||||
let _v: Vec<u8> = Vec::with_capacity(1);
|
let v: Vec<u8> = Vec::with_capacity(1);
|
||||||
|
// We don't make it here in debug mode, but in release mode,
|
||||||
|
// pushing one element doesn't trigger an allocation. Instead,
|
||||||
|
// we use a box to force it onto the heap
|
||||||
|
assert_eq!(protection_level(), 1);
|
||||||
|
let _b = Box::new(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7,64 +7,58 @@ use qadapt::QADAPT;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static Q: QADAPT = QADAPT;
|
static Q: QADAPT = QADAPT;
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn allocates() {
|
|
||||||
assert_eq!(::qadapt::protection_level(), 1);
|
|
||||||
// Without boxing, release profile can actually optimize out the allocation
|
|
||||||
let mut v = Box::new(Vec::new());
|
|
||||||
v.push(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allocate_panic]
|
#[allocate_panic]
|
||||||
fn no_allocate() {
|
fn no_allocate() {
|
||||||
|
#[cfg(not(release))]
|
||||||
|
{
|
||||||
|
let _v = 0;
|
||||||
|
}
|
||||||
assert_eq!(::qadapt::protection_level(), 1);
|
assert_eq!(::qadapt::protection_level(), 1);
|
||||||
let _v: Vec<()> = Vec::with_capacity(0);
|
let _v: Vec<()> = Vec::with_capacity(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn no_allocate_ret() -> bool {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn no_allocate_implicit_ret() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn no_allocate_arg(b: bool) -> bool {
|
|
||||||
b
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn no_allocate_args(_b: bool, _u: usize, i: i64) -> i64 {
|
|
||||||
i
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allocate_panic]
|
|
||||||
fn return_result(r: Result<usize, io::Error>) -> Result<Result<usize, io::Error>, ()> {
|
|
||||||
Ok(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_no_allocate() {
|
fn macro_no_allocate() {
|
||||||
no_allocate();
|
no_allocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn allocates() {
|
||||||
|
assert_eq!(::qadapt::protection_level(), 1);
|
||||||
|
// Without boxing, release profile can actually optimize out the allocation
|
||||||
|
let mut v = Box::new(Vec::new());
|
||||||
|
v.push(1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn macro_allocates() {
|
fn macro_allocates() {
|
||||||
allocates();
|
allocates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn no_allocate_ret() -> bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_return() {
|
fn macro_return() {
|
||||||
assert!(no_allocate_ret());
|
assert!(no_allocate_ret());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn no_allocate_implicit_ret() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_implicit_return() {
|
fn macro_implicit_return() {
|
||||||
assert!(no_allocate_ret());
|
assert!(no_allocate_implicit_ret());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn no_allocate_arg(b: bool) -> bool {
|
||||||
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -73,12 +67,22 @@ fn macro_allocate_arg() {
|
|||||||
no_allocate_arg(false);
|
no_allocate_arg(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn no_allocate_args(_b: bool, _u: usize, i: i64) -> i64 {
|
||||||
|
i
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_allocate_args() {
|
fn macro_allocate_args() {
|
||||||
no_allocate_args(true, 0, -1);
|
no_allocate_args(true, 0, -1);
|
||||||
no_allocate_args(false, 4, -90);
|
no_allocate_args(false, 4, -90);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allocate_panic]
|
||||||
|
fn return_result(r: Result<usize, io::Error>) -> Result<Result<usize, io::Error>, ()> {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_return_result() {
|
fn macro_return_result() {
|
||||||
return_result(Ok(16)).unwrap().unwrap();
|
return_result(Ok(16)).unwrap().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user