@@ -414,46 +414,42 @@ pub mod fast {
414
414
}
415
415
416
416
// `try_initialize` is only called once per fast thread local variable,
417
- // except in corner cases where it is being recursively initialized.
417
+ // except in corner cases where thread_local dtors reference other
418
+ // thread_local's, or it is being recursively initialized.
419
+ //
420
+ // Macos: Inlining this function can cause two `tlv_get_addr` calls to
421
+ // be performed for every call to `Key::get`. The #[cold] hint makes
422
+ // that less likely.
423
+ // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
418
424
#[ cold]
419
425
unsafe fn try_initialize < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
420
- if mem:: needs_drop :: < T > ( ) {
421
- self . try_initialize_drop ( init)
422
- } else {
426
+ if !mem:: needs_drop :: < T > ( ) || self . try_register_dtor ( ) {
423
427
Some ( self . inner . initialize ( init) )
428
+ } else {
429
+ None
424
430
}
425
431
}
426
432
427
- // `try_initialize_drop ` is only called once per fast thread local
433
+ // `try_register_dtor ` is only called once per fast thread local
428
434
// variable, except in corner cases where thread_local dtors reference
429
435
// other thread_local's, or it is being recursively initialized.
430
- //
431
- // Macos: Inlining this function causes two `tlv_get_addr` calls to be
432
- // performed for every call to `Key::get`.
433
- // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
434
- #[ inline( never) ]
435
- #[ cold]
436
- unsafe fn try_initialize_drop < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
437
- // We don't put a `needs_drop` check around this and call it a day
438
- // because this function is not inlined. Unwrapping code gets
439
- // generated for callers of `LocalKey::with` even if we always
440
- // return `Some` here.
436
+ unsafe fn try_register_dtor ( & self ) -> bool {
441
437
match self . dtor_state . get ( ) {
442
438
DtorState :: Unregistered => {
443
439
// dtor registration happens before initialization.
444
440
register_dtor ( self as * const _ as * mut u8 ,
445
441
destroy_value :: < T > ) ;
446
442
self . dtor_state . set ( DtorState :: Registered ) ;
443
+ true
447
444
}
448
445
DtorState :: Registered => {
449
446
// recursively initialized
447
+ true
450
448
}
451
449
DtorState :: RunningOrHasRun => {
452
- return None
450
+ false
453
451
}
454
452
}
455
-
456
- Some ( self . inner . initialize ( init) )
457
453
}
458
454
}
459
455
0 commit comments