@@ -12,9 +12,8 @@ use core::panic::{BoxMeUp, Location, PanicInfo};
12
12
use crate :: any:: Any ;
13
13
use crate :: fmt;
14
14
use crate :: intrinsics;
15
- use crate :: mem:: { self , ManuallyDrop } ;
15
+ use crate :: mem:: { self , ManuallyDrop , MaybeUninit } ;
16
16
use crate :: process;
17
- use crate :: raw;
18
17
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
19
18
use crate :: sys:: stdio:: panic_output;
20
19
use crate :: sys_common:: backtrace:: { self , RustBacktrace } ;
@@ -29,6 +28,31 @@ use crate::io::set_panic;
29
28
#[ cfg( test) ]
30
29
use realstd:: io:: set_panic;
31
30
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
+
32
56
// Binary interface to the panic runtime that the standard library depends on.
33
57
//
34
58
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
@@ -41,12 +65,9 @@ use realstd::io::set_panic;
41
65
// hook up these functions, but it is not this day!
42
66
#[ allow( improper_ctypes) ]
43
67
extern "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 ;
50
71
51
72
/// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
52
73
/// 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>>
250
271
}
251
272
252
273
// 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.
256
277
//
257
278
// We go through a transition where:
258
279
//
@@ -263,7 +284,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
263
284
// * If the closure successfully returns, we write the return value into the
264
285
// data's return slot. Note that `ptr::write` is used as it's overwriting
265
286
// 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
267
288
// in one of two states:
268
289
//
269
290
// 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>>
274
295
//
275
296
// Once we stack all that together we should have the "most efficient'
276
297
// method of calling a catch panic whilst juggling ownership.
277
- let mut any_data = 0 ;
278
- let mut any_vtable = 0 ;
279
298
let mut data = Data { f : ManuallyDrop :: new ( f) } ;
280
299
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 ( ) ;
287
301
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 {
289
305
Ok ( ManuallyDrop :: into_inner ( data. r ) )
290
306
} 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 ( ) ) )
296
308
} ;
297
309
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
+
298
316
fn do_call < F : FnOnce ( ) -> R , R > ( data : * mut u8 ) {
299
317
unsafe {
300
318
let data = data as * mut Data < F , R > ;
0 commit comments