17
17
//! * Executing a panic up to doing the actual implementation
18
18
//! * Shims around "try"
19
19
20
+ use core:: panic:: BoxMeUp ;
21
+
20
22
use io:: prelude:: * ;
21
23
22
24
use any:: Any ;
@@ -27,7 +29,7 @@ use intrinsics;
27
29
use mem;
28
30
use ptr;
29
31
use raw;
30
- use sys:: stdio:: Stderr ;
32
+ use sys:: stdio:: { Stderr , stderr_prints_nothing } ;
31
33
use sys_common:: rwlock:: RWLock ;
32
34
use sys_common:: thread_info;
33
35
use sys_common:: util;
@@ -57,7 +59,7 @@ extern {
57
59
vtable_ptr : * mut usize ) -> u32 ;
58
60
#[ cfg_attr( stage0, unwind) ]
59
61
#[ cfg_attr( not( stage0) , unwind( allowed) ) ]
60
- fn __rust_start_panic ( data : usize , vtable : usize ) -> u32 ;
62
+ fn __rust_start_panic ( payload : usize ) -> u32 ;
61
63
}
62
64
63
65
#[ derive( Copy , Clone ) ]
@@ -164,6 +166,12 @@ fn default_hook(info: &PanicInfo) {
164
166
#[ cfg( feature = "backtrace" ) ]
165
167
use sys_common:: backtrace;
166
168
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
+
167
175
// If this is a double panic, make sure that we print a backtrace
168
176
// for this panic. Otherwise only print it if logging is enabled.
169
177
#[ cfg( feature = "backtrace" ) ]
@@ -213,15 +221,15 @@ fn default_hook(info: &PanicInfo) {
213
221
214
222
let prev = LOCAL_STDERR . with ( |s| s. borrow_mut ( ) . take ( ) ) ;
215
223
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
+ _ => { }
225
233
}
226
234
}
227
235
@@ -346,7 +354,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
346
354
347
355
let mut s = String :: new ( ) ;
348
356
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)
350
358
}
351
359
352
360
/// 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
362
370
// be performed in the parent of this thread instead of the thread that's
363
371
// panicking.
364
372
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
+ }
366
401
}
367
402
368
403
/// 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
371
406
/// This is the entry point or panics from libcore, formatted panics, and
372
407
/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
373
408
/// 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 ,
377
410
message : Option < & fmt:: Arguments > ,
378
411
file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
379
412
let ( file, line, col) = * file_line_col;
@@ -393,7 +426,7 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
393
426
394
427
unsafe {
395
428
let info = PanicInfo :: internal_constructor (
396
- & * payload,
429
+ payload. get ( ) ,
397
430
message,
398
431
Location :: internal_constructor ( file, line, col) ,
399
432
) ;
@@ -421,16 +454,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
421
454
/// Shim around rust_panic. Called by resume_unwind.
422
455
pub fn update_count_then_panic ( msg : Box < Any + Send > ) -> ! {
423
456
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) )
425
471
}
426
472
427
473
/// A private no-mangle function on which to slap yer breakpoints.
428
474
#[ no_mangle]
429
475
#[ 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 ) -> ! {
431
477
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 )
434
480
} ;
435
481
rtabort ! ( "failed to initiate panic, error {}" , code)
436
482
}
0 commit comments