diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2020-03-02 13:59:20 +0000 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2020-03-05 17:36:50 +0000 |
| commit | 1c950e5c6f85422283bb23bb4bad07ae6c3d2fe1 (patch) | |
| tree | 01318bda757bf28d59cdd218b456b99736c613a8 /src/libpanic_unwind | |
| parent | 5953c100d1e9eea5ca70f185e905ea0773a34eb5 (diff) | |
| download | rust-1c950e5c6f85422283bb23bb4bad07ae6c3d2fe1.tar.gz rust-1c950e5c6f85422283bb23bb4bad07ae6c3d2fe1.zip | |
Simplify the try intrinsic by using a callback in the catch block
Diffstat (limited to 'src/libpanic_unwind')
| -rw-r--r-- | src/libpanic_unwind/emcc.rs | 2 | ||||
| -rw-r--r-- | src/libpanic_unwind/lib.rs | 8 | ||||
| -rw-r--r-- | src/libpanic_unwind/payload.rs | 21 | ||||
| -rw-r--r-- | src/libpanic_unwind/seh.rs | 41 |
4 files changed, 26 insertions, 46 deletions
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 117246aa6c9..c7144fe16cd 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -52,7 +52,7 @@ struct Exception { // This needs to be an Option because the object's lifetime follows C++ // semantics: when catch_unwind moves the Box out of the exception it must // still leave the exception object in a valid state because its destructor - // is still going to be called by __cxa_end_catch.. + // is still going to be called by __cxa_end_catch. data: Option<Box<dyn Any + Send>>, } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 20331e8808c..d6c33666938 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -35,8 +35,6 @@ use alloc::boxed::Box; use core::any::Any; use core::panic::BoxMeUp; -// If adding to this list, you should also look at the list of TryPayload types -// defined in payload.rs and likely add to there as well. cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] @@ -62,8 +60,6 @@ cfg_if::cfg_if! { } } -include!("payload.rs"); - extern "C" { /// Handler in libstd called when a panic object is dropped outside of /// `catch_unwind`. @@ -73,9 +69,7 @@ extern "C" { mod dwarf; #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_panic_cleanup( - payload: TryPayload, -) -> *mut (dyn Any + Send + 'static) { +pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } diff --git a/src/libpanic_unwind/payload.rs b/src/libpanic_unwind/payload.rs deleted file mode 100644 index 1234db7da0f..00000000000 --- a/src/libpanic_unwind/payload.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Type definition for the payload argument of the try intrinsic. -// -// This must be kept in sync with the implementations of the try intrinsic. -// -// This file is included by both panic runtimes and libstd. It is part of the -// panic runtime ABI. -cfg_if::cfg_if! { - if #[cfg(target_os = "emscripten")] { - type TryPayload = *mut u8; - } else if #[cfg(target_arch = "wasm32")] { - type TryPayload = *mut u8; - } else if #[cfg(target_os = "hermit")] { - type TryPayload = *mut u8; - } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { - type TryPayload = *mut u8; - } else if #[cfg(target_env = "msvc")] { - type TryPayload = [u64; 2]; - } else { - type TryPayload = *mut u8; - } -} diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index f599f9815a6..c1656023b60 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -49,10 +49,17 @@ use alloc::boxed::Box; use core::any::Any; -use core::mem; -use core::raw; +use core::mem::{self, ManuallyDrop}; use libc::{c_int, c_uint, c_void}; +struct Exception { + // This needs to be an Option because we catch the exception by reference + // and its destructor is executed by the C++ runtime. When we take the Box + // out of the exception, we need to leave the exception in a valid state + // for its destructor to run without double-dropping the Box. + data: Option<Box<dyn Any + Send>>, +} + // First up, a whole bunch of type definitions. There's a few platform-specific // oddities here, and a lot that's just blatantly copied from LLVM. The purpose // of all this is to implement the `panic` function below through a call to @@ -186,7 +193,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { properties: 0, pType: ptr!(0), thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 }, - sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int, + sizeOrOffset: mem::size_of::<Exception>() as c_int, copyFunction: ptr!(0), }; @@ -229,16 +236,16 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { // because Box<dyn Any> isn't clonable. macro_rules! define_cleanup { ($abi:tt) => { - unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) { - if (*e)[0] != 0 { - cleanup(*e); + unsafe extern $abi fn exception_cleanup(e: *mut Exception) { + if let Some(b) = e.read().data { + drop(b); super::__rust_drop_panic(); } } #[unwind(allowed)] - unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2], - _src: *mut [u64; 2]) - -> *mut [u64; 2] { + unsafe extern $abi fn exception_copy(_dest: *mut Exception, + _src: *mut Exception) + -> *mut Exception { panic!("Rust panics cannot be copied"); } } @@ -258,12 +265,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { // need to otherwise transfer `data` to the heap. We just pass a stack // pointer to this function. // - // The first argument is the payload being thrown (our two pointers), and - // the second argument is the type information object describing the - // exception (constructed above). - let ptrs = mem::transmute::<_, raw::TraitObject>(data); - let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64]; - let throw_ptr = ptrs.as_mut_ptr() as *mut _; + // The ManuallyDrop is needed here since we don't want Exception to be + // dropped when unwinding. Instead it will be dropped by exception_cleanup + // which is invoked by the C++ runtime. + let mut exception = ManuallyDrop::new(Exception { data: Some(data) }); + let throw_ptr = &mut exception as *mut _ as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the // pointers between these structure are just that, pointers. On 64-bit MSVC, @@ -311,8 +317,9 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -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 _ }) +pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> { + let exception = &mut *(payload as *mut Exception); + exception.data.take().unwrap() } // This is required by the compiler to exist (e.g., it's a lang item), but |
