1717//! * Executing a panic up to doing the actual implementation
1818//! * Shims around "try"
1919
20+ use core:: panic:: BoxMeUp ;
21+
2022use io:: prelude:: * ;
2123
2224use any:: Any ;
@@ -27,7 +29,7 @@ use intrinsics;
2729use mem;
2830use ptr;
2931use raw;
30- use sys:: stdio:: Stderr ;
32+ use sys:: stdio:: { Stderr , stderr_prints_nothing } ;
3133use sys_common:: rwlock:: RWLock ;
3234use sys_common:: thread_info;
3335use sys_common:: util;
@@ -56,7 +58,7 @@ extern {
5658 data_ptr : * mut usize ,
5759 vtable_ptr : * mut usize ) -> u32 ;
5860 #[ unwind( allowed) ]
59- fn __rust_start_panic ( data : usize , vtable : usize ) -> u32 ;
61+ fn __rust_start_panic ( payload : usize ) -> u32 ;
6062}
6163
6264#[ derive( Copy , Clone ) ]
@@ -163,6 +165,12 @@ fn default_hook(info: &PanicInfo) {
163165 #[ cfg( feature = "backtrace" ) ]
164166 use sys_common:: backtrace;
165167
168+ // Some platforms know that printing to stderr won't ever actually print
169+ // anything, and if that's the case we can skip everything below.
170+ if stderr_prints_nothing ( ) {
171+ return
172+ }
173+
166174 // If this is a double panic, make sure that we print a backtrace
167175 // for this panic. Otherwise only print it if logging is enabled.
168176 #[ cfg( feature = "backtrace" ) ]
@@ -212,15 +220,15 @@ fn default_hook(info: &PanicInfo) {
212220
213221 let prev = LOCAL_STDERR . with ( |s| s. borrow_mut ( ) . take ( ) ) ;
214222 match ( prev, err. as_mut ( ) ) {
215- ( Some ( mut stderr) , _) => {
216- write ( & mut * stderr) ;
217- let mut s = Some ( stderr) ;
218- LOCAL_STDERR . with ( |slot| {
219- * slot. borrow_mut ( ) = s. take ( ) ;
220- } ) ;
221- }
222- ( None , Some ( ref mut err) ) => { write ( err) }
223- _ => { }
223+ ( Some ( mut stderr) , _) => {
224+ write ( & mut * stderr) ;
225+ let mut s = Some ( stderr) ;
226+ LOCAL_STDERR . with ( |slot| {
227+ * slot. borrow_mut ( ) = s. take ( ) ;
228+ } ) ;
229+ }
230+ ( None , Some ( ref mut err) ) => { write ( err) }
231+ _ => { }
224232 }
225233}
226234
@@ -344,7 +352,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
344352
345353 let mut s = String :: new ( ) ;
346354 let _ = s. write_fmt ( * msg) ;
347- rust_panic_with_hook ( Box :: new ( s) , Some ( msg) , file_line_col)
355+ rust_panic_with_hook ( & mut PanicPayload :: new ( s) , Some ( msg) , file_line_col)
348356}
349357
350358/// This is the entry point of panicking for panic!() and assert!().
@@ -360,7 +368,34 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
360368 // be performed in the parent of this thread instead of the thread that's
361369 // panicking.
362370
363- rust_panic_with_hook ( Box :: new ( msg) , None , file_line_col)
371+ rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , None , file_line_col)
372+ }
373+
374+ struct PanicPayload < A > {
375+ inner : Option < A > ,
376+ }
377+
378+ impl < A : Send + ' static > PanicPayload < A > {
379+ fn new ( inner : A ) -> PanicPayload < A > {
380+ PanicPayload { inner : Some ( inner) }
381+ }
382+ }
383+
384+ unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
385+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
386+ let data = match self . inner . take ( ) {
387+ Some ( a) => Box :: new ( a) as Box < Any + Send > ,
388+ None => Box :: new ( ( ) ) ,
389+ } ;
390+ Box :: into_raw ( data)
391+ }
392+
393+ fn get ( & self ) -> & ( Any + Send ) {
394+ match self . inner {
395+ Some ( ref a) => a,
396+ None => & ( ) ,
397+ }
398+ }
364399}
365400
366401/// Executes the primary logic for a panic, including checking for recursive
@@ -369,9 +404,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
369404/// This is the entry point or panics from libcore, formatted panics, and
370405/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
371406/// run panic hooks, and then delegate to the actual implementation of panics.
372- #[ inline( never) ]
373- #[ cold]
374- fn rust_panic_with_hook ( payload : Box < Any + Send > ,
407+ fn rust_panic_with_hook ( payload : & mut BoxMeUp ,
375408 message : Option < & fmt:: Arguments > ,
376409 file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
377410 let ( file, line, col) = * file_line_col;
@@ -391,7 +424,7 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
391424
392425 unsafe {
393426 let info = PanicInfo :: internal_constructor (
394- & * payload,
427+ payload. get ( ) ,
395428 message,
396429 Location :: internal_constructor ( file, line, col) ,
397430 ) ;
@@ -419,16 +452,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
419452/// Shim around rust_panic. Called by resume_unwind.
420453pub fn update_count_then_panic ( msg : Box < Any + Send > ) -> ! {
421454 update_panic_count ( 1 ) ;
422- rust_panic ( msg)
455+
456+ struct RewrapBox ( Box < Any + Send > ) ;
457+
458+ unsafe impl BoxMeUp for RewrapBox {
459+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
460+ Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
461+ }
462+
463+ fn get ( & self ) -> & ( Any + Send ) {
464+ & * self . 0
465+ }
466+ }
467+
468+ rust_panic ( & mut RewrapBox ( msg) )
423469}
424470
425471/// A private no-mangle function on which to slap yer breakpoints.
426472#[ no_mangle]
427473#[ allow( private_no_mangle_fns) ] // yes we get it, but we like breakpoints
428- pub fn rust_panic ( msg : Box < Any + Send > ) -> ! {
474+ pub fn rust_panic ( mut msg : & mut BoxMeUp ) -> ! {
429475 let code = unsafe {
430- let obj = mem :: transmute :: < _ , raw :: TraitObject > ( msg) ;
431- __rust_start_panic ( obj. data as usize , obj . vtable as usize )
476+ let obj = & mut msg as * mut & mut BoxMeUp ;
477+ __rust_start_panic ( obj as usize )
432478 } ;
433479 rtabort ! ( "failed to initiate panic, error {}" , code)
434480}
0 commit comments