about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJames Miller <james@aatch.net>2015-01-21 00:46:02 +1300
committerJames Miller <james@aatch.net>2015-01-21 00:46:02 +1300
commita729a404945de10f99e2530a5c28952996532b29 (patch)
treea4bd2a7171deb6edf5bab96ecc4c3896c5ed2a7f
parent65b61ffb3f55c996eceded6c91281911b671d978 (diff)
downloadrust-a729a404945de10f99e2530a5c28952996532b29.tar.gz
rust-a729a404945de10f99e2530a5c28952996532b29.zip
Use assume to inform the optimiser about refcount invariants
The reference count can never be 0, unless we're about to drop the data
completely. Using the `assume` intrinsic allows us to inform LLVM about
that invariant, meaning it can avoid unnecessary drops.
-rw-r--r--src/liballoc/rc.rs15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 7191a7af346..0f2a11cc1db 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -160,6 +160,7 @@ use core::option::Option::{Some, None};
 use core::ptr::{self, PtrExt};
 use core::result::Result;
 use core::result::Result::{Ok, Err};
+use core::intrinsics::assume;
 
 use heap::deallocate;
 
@@ -905,10 +906,20 @@ trait RcBoxPtr<T> {
     fn strong(&self) -> uint { self.inner().strong.get() }
 
     #[inline]
-    fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
+    fn inc_strong(&self) {
+        let strong = self.strong();
+        // The reference count is always at least one unless we're about to drop the type
+        unsafe { assume(strong > 0); }
+        self.inner().strong.set(strong + 1);
+    }
 
     #[inline]
-    fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
+    fn dec_strong(&self) {
+        let strong = self.strong();
+        // The reference count is always at least one unless we're about to drop the type
+        unsafe { assume(strong > 0); }
+        self.inner().strong.set(strong - 1);
+    }
 
     #[inline]
     fn weak(&self) -> uint { self.inner().weak.get() }