diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-06-10 13:14:26 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-06-10 13:14:26 +0200 |
| commit | 97df8676b7fb856e396057b8ecfc231489456b10 (patch) | |
| tree | 7a775d0f30b4e613deca7f01a977ba8781c6c01e | |
| parent | 1cbd8a4d686d1411105f26cddf876c5994e69593 (diff) | |
| parent | a4a07e00ced90e076dbadd8b350db527bcc588bd (diff) | |
| download | rust-97df8676b7fb856e396057b8ecfc231489456b10.tar.gz rust-97df8676b7fb856e396057b8ecfc231489456b10.zip | |
Rollup merge of #59600 - tobia:master, r=pnkfelix
Replaced linear token counting macros with optimized implementation There are currently two distinct token-counting macros in the source. Both implement the trivial algorithm, with linear complexity. They may or may not be adequate for their use case, but considering that other people are probably going to copy and paste them whenever they need a token-counting macro, I replaced them with an optimized implementation with logarithmic complexity.
| -rw-r--r-- | src/librustc/hir/map/definitions.rs | 12 | ||||
| -rw-r--r-- | src/libserialize/serialize.rs | 17 |
2 files changed, 22 insertions, 7 deletions
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 3edd75fb725..6a561f0c63a 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -582,9 +582,17 @@ impl DefPathData { } } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. macro_rules! count { - () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } // We define the GlobalMetaDataKind enum with this macro because we want to diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 36a1628014d..95095c712d2 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -723,10 +723,17 @@ macro_rules! peel { ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) } -/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3 -macro_rules! count_idents { - () => { 0 }; - ($_i:ident, $($rest:ident,)*) => { 1 + count_idents!($($rest,)*) } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. +macro_rules! count { + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } macro_rules! tuple { @@ -735,7 +742,7 @@ macro_rules! tuple { impl<$($name:Decodable),*> Decodable for ($($name,)*) { #[allow(non_snake_case)] fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)*), D::Error> { - let len: usize = count_idents!($($name,)*); + let len: usize = count!($($name)*); d.read_tuple(len, |d| { let mut i = 0; let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> { |
