about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/panicking.rs88
-rw-r--r--src/libstd/sys/cloudabi/stdio.rs4
-rw-r--r--src/libstd/sys/redox/stdio.rs4
-rw-r--r--src/libstd/sys/unix/stdio.rs4
-rw-r--r--src/libstd/sys/wasm/rwlock.rs4
-rw-r--r--src/libstd/sys/wasm/stdio.rs4
-rw-r--r--src/libstd/sys/windows/stdio.rs4
-rw-r--r--src/libstd/sys_common/backtrace.rs13
-rw-r--r--src/libstd/sys_common/mod.rs14
-rw-r--r--src/libstd/sys_common/thread_local.rs4
-rw-r--r--src/libstd/sys_common/util.rs5
-rw-r--r--src/libstd/thread/local.rs41
-rw-r--r--src/libstd/thread/mod.rs3
14 files changed, 154 insertions, 39 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index a34fcb5a7f9..dd96c57538c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -292,6 +292,7 @@
 #![feature(rand)]
 #![feature(raw)]
 #![feature(rustc_attrs)]
+#![feature(std_internals)]
 #![feature(stdsimd)]
 #![feature(shrink_to)]
 #![feature(slice_bytes)]
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index fba3269204e..715fd45e490 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -17,6 +17,8 @@
 //! * Executing a panic up to doing the actual implementation
 //! * Shims around "try"
 
+use core::panic::BoxMeUp;
+
 use io::prelude::*;
 
 use any::Any;
@@ -27,7 +29,7 @@ use intrinsics;
 use mem;
 use ptr;
 use raw;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use sys_common::rwlock::RWLock;
 use sys_common::thread_info;
 use sys_common::util;
@@ -56,7 +58,7 @@ extern {
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
     #[unwind(allowed)]
-    fn __rust_start_panic(data: usize, vtable: usize) -> u32;
+    fn __rust_start_panic(payload: usize) -> u32;
 }
 
 #[derive(Copy, Clone)]
@@ -163,6 +165,12 @@ fn default_hook(info: &PanicInfo) {
     #[cfg(feature = "backtrace")]
     use sys_common::backtrace;
 
+    // Some platforms know that printing to stderr won't ever actually print
+    // anything, and if that's the case we can skip everything below.
+    if stderr_prints_nothing() {
+        return
+    }
+
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
     #[cfg(feature = "backtrace")]
@@ -212,15 +220,15 @@ fn default_hook(info: &PanicInfo) {
 
     let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
     match (prev, err.as_mut()) {
-        (Some(mut stderr), _) => {
-            write(&mut *stderr);
-            let mut s = Some(stderr);
-            LOCAL_STDERR.with(|slot| {
-                *slot.borrow_mut() = s.take();
-            });
-        }
-        (None, Some(ref mut err)) => { write(err) }
-        _ => {}
+       (Some(mut stderr), _) => {
+           write(&mut *stderr);
+           let mut s = Some(stderr);
+           LOCAL_STDERR.with(|slot| {
+               *slot.borrow_mut() = s.take();
+           });
+       }
+       (None, Some(ref mut err)) => { write(err) }
+       _ => {}
     }
 }
 
@@ -344,7 +352,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
 
     let mut s = String::new();
     let _ = s.write_fmt(*msg);
-    rust_panic_with_hook(Box::new(s), Some(msg), file_line_col)
+    rust_panic_with_hook(&mut PanicPayload::new(s), Some(msg), file_line_col)
 }
 
 /// This is the entry point of panicking for panic!() and assert!().
@@ -360,7 +368,34 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
     // be performed in the parent of this thread instead of the thread that's
     // panicking.
 
-    rust_panic_with_hook(Box::new(msg), None, file_line_col)
+    rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col)
+}
+
+struct PanicPayload<A> {
+    inner: Option<A>,
+}
+
+impl<A: Send + 'static> PanicPayload<A> {
+    fn new(inner: A) -> PanicPayload<A> {
+        PanicPayload { inner: Some(inner) }
+    }
+}
+
+unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
+    fn box_me_up(&mut self) -> *mut (Any + Send) {
+        let data = match self.inner.take() {
+            Some(a) => Box::new(a) as Box<Any + Send>,
+            None => Box::new(()),
+        };
+        Box::into_raw(data)
+    }
+
+    fn get(&self) -> &(Any + Send) {
+        match self.inner {
+            Some(ref a) => a,
+            None => &(),
+        }
+    }
 }
 
 /// Executes the primary logic for a panic, including checking for recursive
@@ -369,9 +404,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
 /// This is the entry point or panics from libcore, formatted panics, and
 /// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
 /// run panic hooks, and then delegate to the actual implementation of panics.
-#[inline(never)]
-#[cold]
-fn rust_panic_with_hook(payload: Box<Any + Send>,
+fn rust_panic_with_hook(payload: &mut BoxMeUp,
                         message: Option<&fmt::Arguments>,
                         file_line_col: &(&'static str, u32, u32)) -> ! {
     let (file, line, col) = *file_line_col;
@@ -391,7 +424,7 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
 
     unsafe {
         let info = PanicInfo::internal_constructor(
-            &*payload,
+            payload.get(),
             message,
             Location::internal_constructor(file, line, col),
         );
@@ -419,16 +452,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
 /// Shim around rust_panic. Called by resume_unwind.
 pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
     update_panic_count(1);
-    rust_panic(msg)
+
+    struct RewrapBox(Box<Any + Send>);
+
+    unsafe impl BoxMeUp for RewrapBox {
+        fn box_me_up(&mut self) -> *mut (Any + Send) {
+            Box::into_raw(mem::replace(&mut self.0, Box::new(())))
+        }
+
+        fn get(&self) -> &(Any + Send) {
+            &*self.0
+        }
+    }
+
+    rust_panic(&mut RewrapBox(msg))
 }
 
 /// A private no-mangle function on which to slap yer breakpoints.
 #[no_mangle]
 #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
-pub fn rust_panic(msg: Box<Any + Send>) -> ! {
+pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! {
     let code = unsafe {
-        let obj = mem::transmute::<_, raw::TraitObject>(msg);
-        __rust_start_panic(obj.data as usize, obj.vtable as usize)
+        let obj = &mut msg as *mut &mut BoxMeUp;
+        __rust_start_panic(obj as usize)
     };
     rtabort!("failed to initiate panic, error {}", code)
 }
diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs
index 9519a926471..1d7344f921c 100644
--- a/src/libstd/sys/cloudabi/stdio.rs
+++ b/src/libstd/sys/cloudabi/stdio.rs
@@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs
index 3abb094ac34..7a4d11b0ecb 100644
--- a/src/libstd/sys/redox/stdio.rs
+++ b/src/libstd/sys/redox/stdio.rs
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index e9b3d4affc7..87ba2aef4f1 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs
index 8b06f541674..6516010af47 100644
--- a/src/libstd/sys/wasm/rwlock.rs
+++ b/src/libstd/sys/wasm/rwlock.rs
@@ -30,7 +30,7 @@ impl RWLock {
         if *mode >= 0 {
             *mode += 1;
         } else {
-            panic!("rwlock locked for writing");
+            rtabort!("rwlock locked for writing");
         }
     }
 
@@ -51,7 +51,7 @@ impl RWLock {
         if *mode == 0 {
             *mode = -1;
         } else {
-            panic!("rwlock locked for reading")
+            rtabort!("rwlock locked for reading")
         }
     }
 
diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs
index beb19c0ed2c..023f29576a2 100644
--- a/src/libstd/sys/wasm/stdio.rs
+++ b/src/libstd/sys/wasm/stdio.rs
@@ -69,3 +69,7 @@ pub const STDIN_BUF_SIZE: usize = 0;
 pub fn is_ebadf(_err: &io::Error) -> bool {
     true
 }
+
+pub fn stderr_prints_nothing() -> bool {
+    !cfg!(feature = "wasm_syscall")
+}
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index b43df20bddd..81b89da21d3 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 // idea is that on windows we use a slightly smaller buffer that's
 // been seen to be acceptable.
 pub const STDIN_BUF_SIZE: usize = 8 * 1024;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 1955f3ec9a2..20109d2d0d5 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -139,10 +139,10 @@ pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
 /// Controls how the backtrace should be formatted.
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum PrintFormat {
-    /// Show all the frames with absolute path for files.
-    Full = 2,
     /// Show only relevant data from the backtrace.
-    Short = 3,
+    Short = 2,
+    /// Show all the frames with absolute path for files.
+    Full = 3,
 }
 
 // For now logging is turned off by default, and this function checks to see
@@ -150,11 +150,10 @@ pub enum PrintFormat {
 pub fn log_enabled() -> Option<PrintFormat> {
     static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
     match ENABLED.load(Ordering::SeqCst) {
-        0 => {},
+        0 => {}
         1 => return None,
-        2 => return Some(PrintFormat::Full),
-        3 => return Some(PrintFormat::Short),
-        _ => unreachable!(),
+        2 => return Some(PrintFormat::Short),
+        _ => return Some(PrintFormat::Full),
     }
 
     let val = match env::var_os("RUST_BACKTRACE") {
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 27504d374dd..d0c4d6a7737 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -28,6 +28,16 @@
 use sync::Once;
 use sys;
 
+macro_rules! rtabort {
+    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
+}
+
+macro_rules! rtassert {
+    ($e:expr) => (if !$e {
+        rtabort!(concat!("assertion failed: ", stringify!($e)));
+    })
+}
+
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
@@ -101,10 +111,6 @@ pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
     if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
 }
 
-macro_rules! rtabort {
-    ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
-}
-
 /// One-time runtime cleanup.
 pub fn cleanup() {
     static CLEANUP: Once = Once::new();
diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs
index a4aa3d96d25..d0d6224de0a 100644
--- a/src/libstd/sys_common/thread_local.rs
+++ b/src/libstd/sys_common/thread_local.rs
@@ -169,7 +169,7 @@ impl StaticKey {
                 self.key.store(key, Ordering::SeqCst);
             }
             INIT_LOCK.unlock();
-            assert!(key != 0);
+            rtassert!(key != 0);
             return key
         }
 
@@ -190,7 +190,7 @@ impl StaticKey {
             imp::destroy(key1);
             key2
         };
-        assert!(key != 0);
+        rtassert!(key != 0);
         match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
             // The CAS succeeded, so we've created the actual key
             0 => key as usize,
diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs
index a391c7cc6ef..a373e980b97 100644
--- a/src/libstd/sys_common/util.rs
+++ b/src/libstd/sys_common/util.rs
@@ -10,10 +10,13 @@
 
 use fmt;
 use io::prelude::*;
-use sys::stdio::Stderr;
+use sys::stdio::{Stderr, stderr_prints_nothing};
 use thread;
 
 pub fn dumb_print(args: fmt::Arguments) {
+    if stderr_prints_nothing() {
+        return
+    }
     let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
 }
 
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 99479bc56ef..40d3280baa6 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -172,12 +172,16 @@ macro_rules! __thread_local_inner {
                 &'static $crate::cell::UnsafeCell<
                     $crate::option::Option<$t>>>
             {
+                #[cfg(target_arch = "wasm32")]
+                static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
+                    $crate::thread::__StaticLocalKeyInner::new();
+
                 #[thread_local]
-                #[cfg(target_thread_local)]
+                #[cfg(all(target_thread_local, not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
-                #[cfg(not(target_thread_local))]
+                #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
 
@@ -295,6 +299,39 @@ impl<T: 'static> LocalKey<T> {
     }
 }
 
+/// On some platforms like wasm32 there's no threads, so no need to generate
+/// thread locals and we can instead just use plain statics!
+#[doc(hidden)]
+#[cfg(target_arch = "wasm32")]
+pub mod statik {
+    use cell::UnsafeCell;
+    use fmt;
+
+    pub struct Key<T> {
+        inner: UnsafeCell<Option<T>>,
+    }
+
+    unsafe impl<T> ::marker::Sync for Key<T> { }
+
+    impl<T> fmt::Debug for Key<T> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            f.pad("Key { .. }")
+        }
+    }
+
+    impl<T> Key<T> {
+        pub const fn new() -> Key<T> {
+            Key {
+                inner: UnsafeCell::new(None),
+            }
+        }
+
+        pub unsafe fn get(&self) -> Option<&'static UnsafeCell<Option<T>>> {
+            Some(&*(&self.inner as *const _))
+        }
+    }
+}
+
 #[doc(hidden)]
 #[cfg(target_thread_local)]
 pub mod fast {
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 71aee673cfe..1b976b79b4c 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -203,6 +203,9 @@ pub use self::local::{LocalKey, AccessError};
 // where available, but both are needed.
 
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[cfg(target_arch = "wasm32")]
+#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner;
+#[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[cfg(target_thread_local)]
 #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]