@@ -12,9 +12,8 @@ use core::panic::{BoxMeUp, Location, PanicInfo};
1212use crate :: any:: Any ;
1313use crate :: fmt;
1414use crate :: intrinsics;
15- use crate :: mem:: { self , ManuallyDrop } ;
15+ use crate :: mem:: { self , ManuallyDrop , MaybeUninit } ;
1616use crate :: process;
17- use crate :: raw;
1817use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
1918use crate :: sys:: stdio:: panic_output;
2019use crate :: sys_common:: backtrace:: { self , RustBacktrace } ;
@@ -29,6 +28,31 @@ use crate::io::set_panic;
2928#[ cfg( test) ]
3029use realstd:: io:: set_panic;
3130
31+ // This must be kept in sync with the implementations in libpanic_unwind.
32+ //
33+ // This is *not* checked in anyway; the compiler does not allow us to use a
34+ // type/macro/anything from panic_unwind, since we're then linking in the
35+ // panic_unwind runtime even during -Cpanic=abort.
36+ //
37+ // Essentially this must be the type of `imp::Payload` in libpanic_unwind.
38+ cfg_if:: cfg_if! {
39+ if #[ cfg( not( feature = "panic_unwind" ) ) ] {
40+ type Payload = ( ) ;
41+ } else if #[ cfg( target_os = "emscripten" ) ] {
42+ type Payload = * mut u8 ;
43+ } else if #[ cfg( target_arch = "wasm32" ) ] {
44+ type Payload = * mut u8 ;
45+ } else if #[ cfg( target_os = "hermit" ) ] {
46+ type Payload = * mut u8 ;
47+ } else if #[ cfg( all( target_env = "msvc" , target_arch = "aarch64" ) ) ] {
48+ type Payload = * mut u8 ;
49+ } else if #[ cfg( target_env = "msvc" ) ] {
50+ type Payload = [ u64 ; 2 ] ;
51+ } else {
52+ type Payload = * mut u8 ;
53+ }
54+ }
55+
3256// Binary interface to the panic runtime that the standard library depends on.
3357//
3458// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
@@ -41,12 +65,10 @@ use realstd::io::set_panic;
4165// hook up these functions, but it is not this day!
4266#[ allow( improper_ctypes) ]
4367extern "C" {
44- fn __rust_maybe_catch_panic (
45- f : fn ( * mut u8 ) ,
46- data : * mut u8 ,
47- data_ptr : * mut usize ,
48- vtable_ptr : * mut usize ,
49- ) -> u32 ;
68+ /// The payload ptr here is actually the same as the payload ptr for the try
69+ /// intrinsic (i.e., is really `*mut [u64; 2]` or `*mut *mut u8`).
70+ #[ unwind( allowed) ]
71+ fn __rust_panic_cleanup ( payload : * mut u8 ) -> core:: raw:: TraitObject ;
5072
5173 /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
5274 /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
@@ -241,9 +263,9 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
241263 }
242264
243265 // We do some sketchy operations with ownership here for the sake of
244- // performance. We can only pass pointers down to
245- // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
246- // the ownership tracking here manually using a union.
266+ // performance. We can only pass pointers down to `do_call` (can't pass
267+ // objects by value), so we do all the ownership tracking here manually
268+ // using a union.
247269 //
248270 // We go through a transition where:
249271 //
@@ -254,7 +276,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
254276 // * If the closure successfully returns, we write the return value into the
255277 // data's return slot. Note that `ptr::write` is used as it's overwriting
256278 // uninitialized data.
257- // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
279+ // * Finally, when we come back out of the `try` intrinsic we're
258280 // in one of two states:
259281 //
260282 // 1. The closure didn't panic, in which case the return value was
@@ -265,28 +287,25 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
265287 //
266288 // Once we stack all that together we should have the "most efficient'
267289 // method of calling a catch panic whilst juggling ownership.
268- let mut any_data = 0 ;
269- let mut any_vtable = 0 ;
270290 let mut data = Data { f : ManuallyDrop :: new ( f) } ;
271291
272- let r = __rust_maybe_catch_panic (
273- do_call :: < F , R > ,
274- & mut data as * mut _ as * mut u8 ,
275- & mut any_data,
276- & mut any_vtable,
277- ) ;
292+ let mut payload: MaybeUninit < Payload > = MaybeUninit :: uninit ( ) ;
278293
279- return if r == 0 {
294+ let data_ptr = & mut data as * mut _ as * mut u8 ;
295+ let payload_ptr = payload. as_mut_ptr ( ) as * mut _ ;
296+ return if intrinsics:: r#try ( do_call :: < F , R > , data_ptr, payload_ptr) == 0 {
280297 debug_assert ! ( update_panic_count( 0 ) == 0 ) ;
281298 Ok ( ManuallyDrop :: into_inner ( data. r ) )
282299 } else {
300+ Err ( cleanup ( payload. assume_init ( ) ) )
301+ } ;
302+
303+ unsafe fn cleanup ( mut payload : Payload ) -> Box < dyn Any + Send + ' static > {
304+ let obj = crate :: mem:: transmute ( __rust_panic_cleanup ( & mut payload as * mut _ as * mut u8 ) ) ;
283305 update_panic_count ( -1 ) ;
284306 debug_assert ! ( update_panic_count( 0 ) == 0 ) ;
285- Err ( mem:: transmute ( raw:: TraitObject {
286- data : any_data as * mut _ ,
287- vtable : any_vtable as * mut _ ,
288- } ) )
289- } ;
307+ obj
308+ }
290309
291310 fn do_call < F : FnOnce ( ) -> R , R > ( data : * mut u8 ) {
292311 unsafe {
0 commit comments