about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-08 00:31:42 +0000
committerbors <bors@rust-lang.org>2014-07-08 00:31:42 +0000
commita3257804df2bace236f83d9e5a9e887a1df30ef5 (patch)
treec363f1128a77eade9cfd55fc52589f4aaf7681d8 /src/libcore
parent00cdd639a93ec1dcad85cebc52214eeba0441c93 (diff)
parentfa8da9d6b317f39402f1127575e2bd08db33c508 (diff)
downloadrust-a3257804df2bace236f83d9e5a9e887a1df30ef5.tar.gz
rust-a3257804df2bace236f83d9e5a9e887a1df30ef5.zip
auto merge of #15406 : luqmana/rust/nop, r=pcwalton
Extend the null ptr optimization to work with slices, closures, procs, & trait objects by using the internal pointers as the discriminant.

This decreases the size of `Option<&[int]>` (and similar) by one word.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/slice.rs36
1 files changed, 24 insertions, 12 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 0178c0318b8..8197a7c2dcb 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -884,17 +884,20 @@ macro_rules! iterator {
                     if self.ptr == self.end {
                         None
                     } else {
-                        let old = self.ptr;
-                        self.ptr = if mem::size_of::<T>() == 0 {
+                        if mem::size_of::<T>() == 0 {
                             // purposefully don't use 'ptr.offset' because for
                             // vectors with 0-size elements this would return the
                             // same pointer.
-                            transmute(self.ptr as uint + 1)
+                            self.ptr = transmute(self.ptr as uint + 1);
+
+                            // Use a non-null pointer value
+                            Some(transmute(1u))
                         } else {
-                            self.ptr.offset(1)
-                        };
+                            let old = self.ptr;
+                            self.ptr = self.ptr.offset(1);
 
-                        Some(transmute(old))
+                            Some(transmute(old))
+                        }
                     }
                 }
             }
@@ -916,13 +919,17 @@ macro_rules! iterator {
                     if self.end == self.ptr {
                         None
                     } else {
-                        self.end = if mem::size_of::<T>() == 0 {
+                        if mem::size_of::<T>() == 0 {
                             // See above for why 'ptr.offset' isn't used
-                            transmute(self.end as uint - 1)
+                            self.end = transmute(self.end as uint - 1);
+
+                            // Use a non-null pointer value
+                            Some(transmute(1u))
                         } else {
-                            self.end.offset(-1)
-                        };
-                        Some(transmute(self.end))
+                            self.end = self.end.offset(-1);
+
+                            Some(transmute(self.end))
+                        }
                     }
                 }
             }
@@ -956,7 +963,12 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
     fn idx(&mut self, index: uint) -> Option<&'a T> {
         unsafe {
             if index < self.indexable() {
-                transmute(self.ptr.offset(index as int))
+                if mem::size_of::<T>() == 0 {
+                    // Use a non-null pointer value
+                    Some(transmute(1u))
+                } else {
+                    Some(transmute(self.ptr.offset(index as int)))
+                }
             } else {
                 None
             }