@@ -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,9 @@ 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+ fn __rust_panic_cleanup ( payload : * mut u8 ) -> core:: raw:: TraitObject ;
5071
5172 /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
5273 /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
@@ -250,9 +271,9 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
250271 }
251272
252273 // We do some sketchy operations with ownership here for the sake of
253- // performance. We can only pass pointers down to
254- // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
255- // the ownership tracking here manually using a union.
274+ // performance. We can only pass pointers down to `do_call` (can't pass
275+ // objects by value), so we do all the ownership tracking here manually
276+ // using a union.
256277 //
257278 // We go through a transition where:
258279 //
@@ -263,7 +284,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
263284 // * If the closure successfully returns, we write the return value into the
264285 // data's return slot. Note that `ptr::write` is used as it's overwriting
265286 // uninitialized data.
266- // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
287+ // * Finally, when we come back out of the `try` intrinsic we're
267288 // in one of two states:
268289 //
269290 // 1. The closure didn't panic, in which case the return value was
@@ -274,27 +295,24 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
274295 //
275296 // Once we stack all that together we should have the "most efficient'
276297 // method of calling a catch panic whilst juggling ownership.
277- let mut any_data = 0 ;
278- let mut any_vtable = 0 ;
279298 let mut data = Data { f : ManuallyDrop :: new ( f) } ;
280299
281- let r = __rust_maybe_catch_panic (
282- do_call :: < F , R > ,
283- & mut data as * mut _ as * mut u8 ,
284- & mut any_data,
285- & mut any_vtable,
286- ) ;
300+ let mut payload: MaybeUninit < Payload > = MaybeUninit :: uninit ( ) ;
287301
288- return if r == 0 {
302+ let data_ptr = & mut data as * mut _ as * mut u8 ;
303+ let payload_ptr = payload. as_mut_ptr ( ) as * mut _ ;
304+ return if intrinsics:: r#try ( do_call :: < F , R > , data_ptr, payload_ptr) == 0 {
289305 Ok ( ManuallyDrop :: into_inner ( data. r ) )
290306 } else {
291- update_panic_count ( -1 ) ;
292- Err ( mem:: transmute ( raw:: TraitObject {
293- data : any_data as * mut _ ,
294- vtable : any_vtable as * mut _ ,
295- } ) )
307+ Err ( cleanup ( payload. assume_init ( ) ) )
296308 } ;
297309
310+ unsafe fn cleanup ( mut payload : Payload ) -> Box < dyn Any + Send + ' static > {
311+ let obj = crate :: mem:: transmute ( __rust_panic_cleanup ( & mut payload as * mut _ as * mut u8 ) ) ;
312+ update_panic_count ( -1 ) ;
313+ obj
314+ }
315+
298316 fn do_call < F : FnOnce ( ) -> R , R > ( data : * mut u8 ) {
299317 unsafe {
300318 let data = data as * mut Data < F , R > ;
0 commit comments