From 55419bdf697801d0dda8a0ba60a6c5c9ffef76ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Tue, 7 Oct 2014 22:38:23 +0200 Subject: [PATCH] Generate better code for "large" vec![] macro invocations Even when optimized, something like vec![1i,2,3,4,5,6,7,8,9,10] will allocate three times, because LLVM can only drop the call based on the observed size of the previous allocation. Using a simple macro to count the number of elements, we can initialize the vector with the correct size and avoid reallocations. Since LLVM already does constant folding for us, the new count!() macro results in a single integer constant even if building without optimizations, so we don't end up with an awful lot of additions in the generated code. --- src/libstd/macros.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index fa356432a6731..3ca46f8f3e138 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -321,7 +321,22 @@ macro_rules! try( ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) ) +/// A macro to count the number of expressions passed to it +#[macro_export] +macro_rules! count( + ($x:expr, $($xs:expr),+) => { + 1 + count!($($xs),+) + }; + ($x:expr) => { + 1u + }; + ($($x:expr),*) => { + 0u + }; +) + /// Create a `std::vec::Vec` containing the arguments. +#[cfg(stage0)] #[macro_export] macro_rules! vec( ($($e:expr),*) => ({ @@ -333,6 +348,18 @@ macro_rules! vec( ($($e:expr),+,) => (vec!($($e),+)) ) +#[not(cfg(stage0))] +#[macro_export] +macro_rules! vec( + ($($e:expr),*) => ({ + // leading _ to allow empty construction without a warning. + let mut _temp = ::std::vec::Vec::with_capacity(count!($($e),*)); + $(_temp.push($e);)* + _temp + }); + ($($e:expr),+,) => (vec!($($e),+)) +) + /// A macro to select an event from a number of receivers. ///