about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobia <tobia.conforto@gruppo4.it>2019-04-01 18:16:03 +0900
committerTobia <tobia.conforto@gruppo4.it>2019-04-13 01:24:10 +0900
commita4a07e00ced90e076dbadd8b350db527bcc588bd (patch)
tree13e55524c00d9acf65a0ef3fe6e0587c617a8480
parenteab3eb38df8dca99110b6149b3a15deeb4ef0413 (diff)
downloadrust-a4a07e00ced90e076dbadd8b350db527bcc588bd.tar.gz
rust-a4a07e00ced90e076dbadd8b350db527bcc588bd.zip
Replaced linear token counting macros with optimized implementation
-rw-r--r--src/librustc/hir/map/definitions.rs12
-rw-r--r--src/libserialize/serialize.rs17
2 files changed, 22 insertions, 7 deletions
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 1006d813e65..c72edb6cc6d 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -696,9 +696,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 cf948078b08..d53891828f1 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> {