about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-02-05 21:08:03 +0000
committerbors <bors@rust-lang.org>2015-02-05 21:08:03 +0000
commit99f6206c4ea9ecaf61feb39521db5dd72cb717b0 (patch)
treea05ff78f8a1a64c4c8f11d61157fd7ec7f5ed438
parent189930fcae287565dcef856ae8d60a83190a4b92 (diff)
parent40b6e34240c6669fdf7fb1b83c3925b0becafd0e (diff)
downloadrust-99f6206c4ea9ecaf61feb39521db5dd72cb717b0.tar.gz
rust-99f6206c4ea9ecaf61feb39521db5dd72cb717b0.zip
Auto merge of #21894 - dotdash:assume_rc, r=alexcrichton
This is half of what @Aatch implemented in #21418. The non-null assumption is later canonicalized to !nonnull metadata and doesn't cause any slowdowns (in fact the build is slightly faster with this change). I left out the other half of #21418 because that still causes a ~16% increase in compile times (30m -> 35m).
-rw-r--r--src/liballoc/rc.rs27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 464f20e9cac..80ffa4a0a19 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;
 
@@ -769,12 +770,34 @@ trait RcBoxPtr<T> {
 
 impl<T> RcBoxPtr<T> for Rc<T> {
     #[inline(always)]
-    fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
+    fn inner(&self) -> &RcBox<T> {
+        unsafe {
+            // Safe to assume this here, as if it weren't true, we'd be breaking
+            // the contract anyway.
+            // This allows the null check to be elided in the destructor if we
+            // manipulated the reference count in the same function.
+            if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
+                assume(!self._ptr.is_null());
+            }
+            &(**self._ptr)
+        }
+    }
 }
 
 impl<T> RcBoxPtr<T> for Weak<T> {
     #[inline(always)]
-    fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
+    fn inner(&self) -> &RcBox<T> {
+        unsafe {
+            // Safe to assume this here, as if it weren't true, we'd be breaking
+            // the contract anyway.
+            // This allows the null check to be elided in the destructor if we
+            // manipulated the reference count in the same function.
+            if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
+                assume(!self._ptr.is_null());
+            }
+            &(**self._ptr)
+        }
+    }
 }
 
 #[cfg(test)]