about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-30 03:46:25 +0000
committerbors <bors@rust-lang.org>2014-06-30 03:46:25 +0000
commite25eb6b223d86047dc807a167f3dd4bf492bbf41 (patch)
treeb0c22f04747ee2122e32e8c101e371be5fca01c8
parent9ae48286a99627391e30da3888217e6050230cfe (diff)
parentab1bd3adf673ef7a515242a2dcc09ce360d41d9c (diff)
downloadrust-e25eb6b223d86047dc807a167f3dd4bf492bbf41.tar.gz
rust-e25eb6b223d86047dc807a167f3dd4bf492bbf41.zip
auto merge of #15256 : erickt/rust/optimizations, r=alexcrichton
The bug #11084 causes `option::collect` and `result::collect` about twice as slower as it should because llvm is having some trouble optimizing away the scan closure. This gets rid of it so now those functions perform equivalent to a hand written version.

This also adds an impl of `Default` for `Rc` along the way.
-rw-r--r--src/liballoc/rc.rs8
-rw-r--r--src/libcollections/hash/sip.rs2
-rw-r--r--src/libcore/option.rs32
-rw-r--r--src/libcore/result.rs32
4 files changed, 52 insertions, 22 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index a3ca72f1547..e3127030842 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -27,6 +27,7 @@ use core::mem::transmute;
 use core::cell::Cell;
 use core::clone::Clone;
 use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
+use core::default::Default;
 use core::kinds::marker;
 use core::ops::{Deref, Drop};
 use core::option::{Option, Some, None};
@@ -152,6 +153,13 @@ impl<T> Clone for Rc<T> {
     }
 }
 
+impl<T: Default> Default for Rc<T> {
+    #[inline]
+    fn default() -> Rc<T> {
+        Rc::new(Default::default())
+    }
+}
+
 impl<T: PartialEq> PartialEq for Rc<T> {
     #[inline(always)]
     fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
diff --git a/src/libcollections/hash/sip.rs b/src/libcollections/hash/sip.rs
index 887b0fb0b8a..4fd98538af7 100644
--- a/src/libcollections/hash/sip.rs
+++ b/src/libcollections/hash/sip.rs
@@ -265,8 +265,6 @@ pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
     state.result()
 }
 
-
-
 #[cfg(test)]
 mod tests {
     use test::Bencher;
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index c0d04ee0b95..b8612ed93e0 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -587,20 +587,32 @@ impl<A> ExactSize<A> for Item<A> {}
 /// ```
 #[inline]
 pub fn collect<T, Iter: Iterator<Option<T>>, V: FromIterator<T>>(iter: Iter) -> Option<V> {
-    // FIXME(#11084): This should be twice as fast once this bug is closed.
-    let mut iter = iter.scan(false, |state, x| {
-        match x {
-            Some(x) => Some(x),
-            None => {
-                *state = true;
-                None
+    // FIXME(#11084): This could be replaced with Iterator::scan when this
+    // performance bug is closed.
+
+    struct Adapter<Iter> {
+        iter: Iter,
+        found_none: bool,
+    }
+
+    impl<T, Iter: Iterator<Option<T>>> Iterator<T> for Adapter<Iter> {
+        #[inline]
+        fn next(&mut self) -> Option<T> {
+            match self.iter.next() {
+                Some(Some(value)) => Some(value),
+                Some(None) => {
+                    self.found_none = true;
+                    None
+                }
+                None => None,
             }
         }
-    });
+    }
 
-    let v: V = FromIterator::from_iter(iter.by_ref());
+    let mut adapter = Adapter { iter: iter, found_none: false };
+    let v: V = FromIterator::from_iter(adapter.by_ref());
 
-    if iter.state {
+    if adapter.found_none {
         None
     } else {
         Some(v)
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index a104d20f4e5..5cbbf30cd36 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -585,20 +585,32 @@ impl<T: Show, E> Result<T, E> {
 /// ```
 #[inline]
 pub fn collect<T, E, Iter: Iterator<Result<T, E>>, V: FromIterator<T>>(iter: Iter) -> Result<V, E> {
-    // FIXME(#11084): This should be twice as fast once this bug is closed.
-    let mut iter = iter.scan(None, |state, x| {
-        match x {
-            Ok(x) => Some(x),
-            Err(err) => {
-                *state = Some(err);
-                None
+    // FIXME(#11084): This could be replaced with Iterator::scan when this
+    // performance bug is closed.
+
+    struct Adapter<Iter, E> {
+        iter: Iter,
+        err: Option<E>,
+    }
+
+    impl<T, E, Iter: Iterator<Result<T, E>>> Iterator<T> for Adapter<Iter, E> {
+        #[inline]
+        fn next(&mut self) -> Option<T> {
+            match self.iter.next() {
+                Some(Ok(value)) => Some(value),
+                Some(Err(err)) => {
+                    self.err = Some(err);
+                    None
+                }
+                None => None,
             }
         }
-    });
+    }
 
-    let v: V = FromIterator::from_iter(iter.by_ref());
+    let mut adapter = Adapter { iter: iter, err: None };
+    let v: V = FromIterator::from_iter(adapter.by_ref());
 
-    match iter.state {
+    match adapter.err {
         Some(err) => Err(err),
         None => Ok(v),
     }