about summary refs log tree commit diff
path: root/src/libpanic_unwind
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2019-12-26 10:02:21 -0500
committerAmanieu d'Antras <amanieu@gmail.com>2020-03-02 11:43:06 +0000
commitd45ce5aed63fb58385705016dfaff1832a58d7c8 (patch)
tree35a9bea734e796c0690399f6ebfc5049994b02f3 /src/libpanic_unwind
parent6b2983af1a85d857ae3a9345ac93ba0564ab7a73 (diff)
downloadrust-d45ce5aed63fb58385705016dfaff1832a58d7c8.tar.gz
rust-d45ce5aed63fb58385705016dfaff1832a58d7c8.zip
Inline catching panics into std::catch_unwind
This allows LLVM to inline the happy path, such that catching unwinding is
zero-cost when no panic occurs. This also allows us to match the code generated
by C++ try/catch.
Diffstat (limited to 'src/libpanic_unwind')
-rw-r--r--src/libpanic_unwind/dummy.rs4
-rw-r--r--src/libpanic_unwind/emcc.rs4
-rw-r--r--src/libpanic_unwind/gcc.rs5
-rw-r--r--src/libpanic_unwind/hermit.rs4
-rw-r--r--src/libpanic_unwind/lib.rs33
-rw-r--r--src/libpanic_unwind/seh.rs4
6 files changed, 13 insertions, 41 deletions
diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs
index 86756326387..30593d3b88a 100644
--- a/src/libpanic_unwind/dummy.rs
+++ b/src/libpanic_unwind/dummy.rs
@@ -6,9 +6,7 @@ use alloc::boxed::Box;
 use core::any::Any;
 use core::intrinsics;
 
-pub fn payload() -> *mut u8 {
-    core::ptr::null_mut()
-}
+pub type Payload = *mut u8;
 
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     intrinsics::abort()
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 9161d49959c..873135414bd 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -48,9 +48,7 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo {
     name: b"rust_panic\0".as_ptr(),
 };
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
+pub type Payload = *mut u8;
 
 struct Exception {
     // This needs to be an Option because the object's lifetime follows C++
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 591ff9d7fdc..dd84a814f48 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -48,7 +48,6 @@
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::ptr;
 
 use crate::dwarf::eh::{self, EHAction, EHContext};
 use libc::{c_int, uintptr_t};
@@ -83,9 +82,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     }
 }
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
+pub type Payload = *mut u8;
 
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     let exception = Box::from_raw(ptr as *mut Exception);
diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs
index 2f53df2861d..8ffb4bcd3df 100644
--- a/src/libpanic_unwind/hermit.rs
+++ b/src/libpanic_unwind/hermit.rs
@@ -6,9 +6,7 @@ use alloc::boxed::Box;
 use core::any::Any;
 use core::ptr;
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
+pub type Payload = *mut u8;
 
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     extern "C" {
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 6383ae39fb6..60ddf70cea5 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -22,20 +22,20 @@
 #![feature(libc)]
 #![feature(nll)]
 #![feature(panic_unwind)]
-#![feature(raw)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(unwind_attributes)]
 #![feature(abi_thiscall)]
+#![feature(rustc_attrs)]
+#![feature(raw)]
 #![panic_runtime]
 #![feature(panic_runtime)]
 
 use alloc::boxed::Box;
-use core::intrinsics;
-use core::mem;
 use core::panic::BoxMeUp;
-use core::raw;
 
+// If adding to this list, you should also look at libstd::panicking's identical
+// list of Payload types and likely add to there as well.
 cfg_if::cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         #[path = "emcc.rs"]
@@ -69,28 +69,11 @@ extern "C" {
 
 mod dwarf;
 
-// Entry point for catching an exception, implemented using the `try` intrinsic
-// in the compiler.
-//
-// The interaction between the `payload` function and the compiler is pretty
-// hairy and tightly coupled, for more information see the compiler's
-// implementation of this.
 #[no_mangle]
-pub unsafe extern "C" fn __rust_maybe_catch_panic(
-    f: fn(*mut u8),
-    data: *mut u8,
-    data_ptr: *mut usize,
-    vtable_ptr: *mut usize,
-) -> u32 {
-    let mut payload = imp::payload();
-    if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 {
-        0
-    } else {
-        let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
-        *data_ptr = obj.data as usize;
-        *vtable_ptr = obj.vtable as usize;
-        1
-    }
+pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> core::raw::TraitObject {
+    let payload = payload as *mut imp::Payload;
+    let payload = *(payload);
+    core::mem::transmute(imp::cleanup(payload))
 }
 
 // Entry point for raising an exception, just delegates to the platform-specific
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index 6f507e85e74..6f464c1ab68 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -308,9 +308,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _);
 }
 
-pub fn payload() -> [u64; 2] {
-    [0; 2]
-}
+pub type Payload = [u64; 2];
 
 pub unsafe fn cleanup(payload: [u64; 2]) -> Box<dyn Any + Send> {
     mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ })