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;
@@ -57,7 +59,7 @@ extern {
5759 vtable_ptr : * mut usize ) -> u32 ;
5860 #[ cfg_attr( stage0, unwind) ]
5961 #[ cfg_attr( not( stage0) , unwind( allowed) ) ]
60- fn __rust_start_panic ( data : usize , vtable : usize ) -> u32 ;
62+ fn __rust_start_panic ( payload : usize ) -> u32 ;
6163}
6264
6365#[ derive( Copy , Clone ) ]
@@ -164,6 +166,12 @@ fn default_hook(info: &PanicInfo) {
164166 #[ cfg( feature = "backtrace" ) ]
165167 use sys_common:: backtrace;
166168
169+ // Some platforms know that printing to stderr won't ever actually print
170+ // anything, and if that's the case we can skip everything below.
171+ if stderr_prints_nothing ( ) {
172+ return
173+ }
174+
167175 // If this is a double panic, make sure that we print a backtrace
168176 // for this panic. Otherwise only print it if logging is enabled.
169177 #[ cfg( feature = "backtrace" ) ]
@@ -213,15 +221,15 @@ fn default_hook(info: &PanicInfo) {
213221
214222 let prev = LOCAL_STDERR . with ( |s| s. borrow_mut ( ) . take ( ) ) ;
215223 match ( prev, err. as_mut ( ) ) {
216- ( Some ( mut stderr) , _) => {
217- write ( & mut * stderr) ;
218- let mut s = Some ( stderr) ;
219- LOCAL_STDERR . with ( |slot| {
220- * slot. borrow_mut ( ) = s. take ( ) ;
221- } ) ;
222- }
223- ( None , Some ( ref mut err) ) => { write ( err) }
224- _ => { }
224+ ( Some ( mut stderr) , _) => {
225+ write ( & mut * stderr) ;
226+ let mut s = Some ( stderr) ;
227+ LOCAL_STDERR . with ( |slot| {
228+ * slot. borrow_mut ( ) = s. take ( ) ;
229+ } ) ;
230+ }
231+ ( None , Some ( ref mut err) ) => { write ( err) }
232+ _ => { }
225233 }
226234}
227235
@@ -346,7 +354,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
346354
347355 let mut s = String :: new ( ) ;
348356 let _ = s. write_fmt ( * msg) ;
349- rust_panic_with_hook ( Box :: new ( s) , Some ( msg) , file_line_col)
357+ rust_panic_with_hook ( & mut PanicPayload :: new ( s) , Some ( msg) , file_line_col)
350358}
351359
352360/// This is the entry point of panicking for panic!() and assert!().
@@ -362,7 +370,34 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
362370 // be performed in the parent of this thread instead of the thread that's
363371 // panicking.
364372
365- rust_panic_with_hook ( Box :: new ( msg) , None , file_line_col)
373+ rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , None , file_line_col)
374+ }
375+
376+ struct PanicPayload < A > {
377+ inner : Option < A > ,
378+ }
379+
380+ impl < A : Send + ' static > PanicPayload < A > {
381+ fn new ( inner : A ) -> PanicPayload < A > {
382+ PanicPayload { inner : Some ( inner) }
383+ }
384+ }
385+
386+ unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
387+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
388+ let data = match self . inner . take ( ) {
389+ Some ( a) => Box :: new ( a) as Box < Any + Send > ,
390+ None => Box :: new ( ( ) ) ,
391+ } ;
392+ Box :: into_raw ( data)
393+ }
394+
395+ fn get ( & self ) -> & ( Any + Send ) {
396+ match self . inner {
397+ Some ( ref a) => a,
398+ None => & ( ) ,
399+ }
400+ }
366401}
367402
368403/// Executes the primary logic for a panic, including checking for recursive
@@ -371,9 +406,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
371406/// This is the entry point or panics from libcore, formatted panics, and
372407/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
373408/// run panic hooks, and then delegate to the actual implementation of panics.
374- #[ inline( never) ]
375- #[ cold]
376- fn rust_panic_with_hook ( payload : Box < Any + Send > ,
409+ fn rust_panic_with_hook ( payload : & mut BoxMeUp ,
377410 message : Option < & fmt:: Arguments > ,
378411 file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
379412 let ( file, line, col) = * file_line_col;
@@ -393,7 +426,7 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
393426
394427 unsafe {
395428 let info = PanicInfo :: internal_constructor (
396- & * payload,
429+ payload. get ( ) ,
397430 message,
398431 Location :: internal_constructor ( file, line, col) ,
399432 ) ;
@@ -421,16 +454,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
421454/// Shim around rust_panic. Called by resume_unwind.
422455pub fn update_count_then_panic ( msg : Box < Any + Send > ) -> ! {
423456 update_panic_count ( 1 ) ;
424- rust_panic ( msg)
457+
458+ struct RewrapBox ( Box < Any + Send > ) ;
459+
460+ unsafe impl BoxMeUp for RewrapBox {
461+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
462+ Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
463+ }
464+
465+ fn get ( & self ) -> & ( Any + Send ) {
466+ & * self . 0
467+ }
468+ }
469+
470+ rust_panic ( & mut RewrapBox ( msg) )
425471}
426472
427473/// A private no-mangle function on which to slap yer breakpoints.
428474#[ no_mangle]
429475#[ allow( private_no_mangle_fns) ] // yes we get it, but we like breakpoints
430- pub fn rust_panic ( msg : Box < Any + Send > ) -> ! {
476+ pub fn rust_panic ( mut msg : & mut BoxMeUp ) -> ! {
431477 let code = unsafe {
432- let obj = mem :: transmute :: < _ , raw :: TraitObject > ( msg) ;
433- __rust_start_panic ( obj. data as usize , obj . vtable as usize )
478+ let obj = & mut msg as * mut & mut BoxMeUp ;
479+ __rust_start_panic ( obj as usize )
434480 } ;
435481 rtabort ! ( "failed to initiate panic, error {}" , code)
436482}
0 commit comments