@@ -201,7 +201,6 @@ use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
201201use rustc_session:: Limit ;
202202use rustc_span:: source_map:: { dummy_spanned, respan, Span , Spanned , DUMMY_SP } ;
203203use rustc_target:: abi:: Size ;
204- use smallvec:: SmallVec ;
205204use std:: iter;
206205use std:: ops:: Range ;
207206use std:: path:: PathBuf ;
@@ -226,6 +225,44 @@ pub struct InliningMap<'tcx> {
226225 inlines : GrowableBitSet < usize > ,
227226}
228227
228+ /// Struct to store mono items in each collecting and if they should
229+ /// be inlined. We call `instantiation_mode` to get their inlining
230+ /// status when inserting new elements, which avoids calling it in
231+ /// `inlining_map.lock_mut()`. See the `collect_items_rec` implementation
232+ /// below.
233+ struct MonoItems < ' tcx > {
234+ // If this is false, we do not need to compute whether items
235+ // will need to be inlined.
236+ compute_inlining : bool ,
237+
238+ // The TyCtxt used to determine whether the a item should
239+ // be inlined.
240+ tcx : TyCtxt < ' tcx > ,
241+
242+ // The collected mono items. The bool field in each element
243+ // indicates whether this element should be inlined.
244+ items : Vec < ( Spanned < MonoItem < ' tcx > > , bool /*inlined*/ ) > ,
245+ }
246+
247+ impl < ' tcx > MonoItems < ' tcx > {
248+ #[ inline]
249+ fn push ( & mut self , item : Spanned < MonoItem < ' tcx > > ) {
250+ self . extend ( [ item] ) ;
251+ }
252+
253+ #[ inline]
254+ fn extend < T : IntoIterator < Item = Spanned < MonoItem < ' tcx > > > > ( & mut self , iter : T ) {
255+ self . items . extend ( iter. into_iter ( ) . map ( |mono_item| {
256+ let inlined = if !self . compute_inlining {
257+ false
258+ } else {
259+ mono_item. node . instantiation_mode ( self . tcx ) == InstantiationMode :: LocalCopy
260+ } ;
261+ ( mono_item, inlined)
262+ } ) )
263+ }
264+ }
265+
229266impl < ' tcx > InliningMap < ' tcx > {
230267 fn new ( ) -> InliningMap < ' tcx > {
231268 InliningMap {
@@ -235,17 +272,23 @@ impl<'tcx> InliningMap<'tcx> {
235272 }
236273 }
237274
238- fn record_accesses ( & mut self , source : MonoItem < ' tcx > , new_targets : & [ ( MonoItem < ' tcx > , bool ) ] ) {
275+ fn record_accesses < ' a > (
276+ & mut self ,
277+ source : MonoItem < ' tcx > ,
278+ new_targets : & ' a [ ( Spanned < MonoItem < ' tcx > > , bool ) ] ,
279+ ) where
280+ ' tcx : ' a ,
281+ {
239282 let start_index = self . targets . len ( ) ;
240283 let new_items_count = new_targets. len ( ) ;
241284 let new_items_count_total = new_items_count + self . targets . len ( ) ;
242285
243286 self . targets . reserve ( new_items_count) ;
244287 self . inlines . ensure ( new_items_count_total) ;
245288
246- for ( i, ( target , inline ) ) in new_targets. iter ( ) . enumerate ( ) {
247- self . targets . push ( * target ) ;
248- if * inline {
289+ for ( i, ( Spanned { node : mono_item , .. } , inlined ) ) in new_targets. into_iter ( ) . enumerate ( ) {
290+ self . targets . push ( * mono_item ) ;
291+ if * inlined {
249292 self . inlines . insert ( i + start_index) ;
250293 }
251294 }
@@ -321,7 +364,7 @@ pub fn collect_crate_mono_items(
321364// start monomorphizing from.
322365fn collect_roots ( tcx : TyCtxt < ' _ > , mode : MonoItemCollectionMode ) -> Vec < MonoItem < ' _ > > {
323366 debug ! ( "collecting roots" ) ;
324- let mut roots = Vec :: new ( ) ;
367+ let mut roots = MonoItems { compute_inlining : false , tcx , items : Vec :: new ( ) } ;
325368
326369 {
327370 let entry_fn = tcx. entry_fn ( ( ) ) ;
@@ -347,8 +390,11 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
347390 // whose predicates hold. Luckily, items that aren't instantiable
348391 // can't actually be used, so we can just skip codegenning them.
349392 roots
393+ . items
350394 . into_iter ( )
351- . filter_map ( |root| root. node . is_instantiable ( tcx) . then_some ( root. node ) )
395+ . filter_map ( |( Spanned { node : mono_item, .. } , _) | {
396+ mono_item. is_instantiable ( tcx) . then_some ( mono_item)
397+ } )
352398 . collect ( )
353399}
354400
@@ -368,7 +414,7 @@ fn collect_items_rec<'tcx>(
368414 }
369415 debug ! ( "BEGIN collect_items_rec({})" , starting_point. node) ;
370416
371- let mut neighbors = Vec :: new ( ) ;
417+ let mut neighbors = MonoItems { compute_inlining : true , tcx , items : Vec :: new ( ) } ;
372418 let recursion_depth_reset;
373419
374420 //
@@ -483,10 +529,9 @@ fn collect_items_rec<'tcx>(
483529 & format ! ( "the above error was encountered while instantiating `{}`" , formatted_item) ,
484530 ) ;
485531 }
532+ inlining_map. lock_mut ( ) . record_accesses ( starting_point. node , & neighbors. items ) ;
486533
487- record_accesses ( tcx, starting_point. node , neighbors. iter ( ) . map ( |i| & i. node ) , inlining_map) ;
488-
489- for neighbour in neighbors {
534+ for ( neighbour, _) in neighbors. items {
490535 collect_items_rec ( tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map) ;
491536 }
492537
@@ -497,25 +542,6 @@ fn collect_items_rec<'tcx>(
497542 debug ! ( "END collect_items_rec({})" , starting_point. node) ;
498543}
499544
500- fn record_accesses < ' a , ' tcx : ' a > (
501- tcx : TyCtxt < ' tcx > ,
502- caller : MonoItem < ' tcx > ,
503- callees : impl Iterator < Item = & ' a MonoItem < ' tcx > > ,
504- inlining_map : MTRef < ' _ , MTLock < InliningMap < ' tcx > > > ,
505- ) {
506- let is_inlining_candidate = |mono_item : & MonoItem < ' tcx > | {
507- mono_item. instantiation_mode ( tcx) == InstantiationMode :: LocalCopy
508- } ;
509-
510- // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
511- // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
512- // instead to avoid creating this `SmallVec`.
513- let accesses: SmallVec < [ _ ; 128 ] > =
514- callees. map ( |mono_item| ( * mono_item, is_inlining_candidate ( mono_item) ) ) . collect ( ) ;
515-
516- inlining_map. lock_mut ( ) . record_accesses ( caller, & accesses) ;
517- }
518-
519545/// Format instance name that is already known to be too long for rustc.
520546/// Show only the first and last 32 characters to avoid blasting
521547/// the user's terminal with thousands of lines of type-name.
@@ -627,7 +653,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
627653struct MirNeighborCollector < ' a , ' tcx > {
628654 tcx : TyCtxt < ' tcx > ,
629655 body : & ' a mir:: Body < ' tcx > ,
630- output : & ' a mut Vec < Spanned < MonoItem < ' tcx > > > ,
656+ output : & ' a mut MonoItems < ' tcx > ,
631657 instance : Instance < ' tcx > ,
632658}
633659
@@ -905,7 +931,7 @@ fn visit_drop_use<'tcx>(
905931 ty : Ty < ' tcx > ,
906932 is_direct_call : bool ,
907933 source : Span ,
908- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
934+ output : & mut MonoItems < ' tcx > ,
909935) {
910936 let instance = Instance :: resolve_drop_in_place ( tcx, ty) ;
911937 visit_instance_use ( tcx, instance, is_direct_call, source, output) ;
@@ -916,7 +942,7 @@ fn visit_fn_use<'tcx>(
916942 ty : Ty < ' tcx > ,
917943 is_direct_call : bool ,
918944 source : Span ,
919- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
945+ output : & mut MonoItems < ' tcx > ,
920946) {
921947 if let ty:: FnDef ( def_id, substs) = * ty. kind ( ) {
922948 let instance = if is_direct_call {
@@ -934,7 +960,7 @@ fn visit_instance_use<'tcx>(
934960 instance : ty:: Instance < ' tcx > ,
935961 is_direct_call : bool ,
936962 source : Span ,
937- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
963+ output : & mut MonoItems < ' tcx > ,
938964) {
939965 debug ! ( "visit_item_use({:?}, is_direct_call={:?})" , instance, is_direct_call) ;
940966 if !should_codegen_locally ( tcx, & instance) {
@@ -1117,7 +1143,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11171143 trait_ty : Ty < ' tcx > ,
11181144 impl_ty : Ty < ' tcx > ,
11191145 source : Span ,
1120- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
1146+ output : & mut MonoItems < ' tcx > ,
11211147) {
11221148 assert ! ( !trait_ty. has_escaping_bound_vars( ) && !impl_ty. has_escaping_bound_vars( ) ) ;
11231149
@@ -1159,7 +1185,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11591185struct RootCollector < ' a , ' tcx > {
11601186 tcx : TyCtxt < ' tcx > ,
11611187 mode : MonoItemCollectionMode ,
1162- output : & ' a mut Vec < Spanned < MonoItem < ' tcx > > > ,
1188+ output : & ' a mut MonoItems < ' tcx > ,
11631189 entry_fn : Option < ( DefId , EntryFnType ) > ,
11641190}
11651191
@@ -1305,7 +1331,7 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
13051331fn create_mono_items_for_default_impls < ' tcx > (
13061332 tcx : TyCtxt < ' tcx > ,
13071333 item : & ' tcx hir:: Item < ' tcx > ,
1308- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
1334+ output : & mut MonoItems < ' tcx > ,
13091335) {
13101336 match item. kind {
13111337 hir:: ItemKind :: Impl ( ref impl_) => {
@@ -1361,11 +1387,7 @@ fn create_mono_items_for_default_impls<'tcx>(
13611387}
13621388
13631389/// Scans the miri alloc in order to find function calls, closures, and drop-glue.
1364- fn collect_miri < ' tcx > (
1365- tcx : TyCtxt < ' tcx > ,
1366- alloc_id : AllocId ,
1367- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
1368- ) {
1390+ fn collect_miri < ' tcx > ( tcx : TyCtxt < ' tcx > , alloc_id : AllocId , output : & mut MonoItems < ' tcx > ) {
13691391 match tcx. global_alloc ( alloc_id) {
13701392 GlobalAlloc :: Static ( def_id) => {
13711393 assert ! ( !tcx. is_thread_local_static( def_id) ) ;
@@ -1396,7 +1418,7 @@ fn collect_miri<'tcx>(
13961418fn collect_neighbours < ' tcx > (
13971419 tcx : TyCtxt < ' tcx > ,
13981420 instance : Instance < ' tcx > ,
1399- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
1421+ output : & mut MonoItems < ' tcx > ,
14001422) {
14011423 debug ! ( "collect_neighbours: {:?}" , instance. def_id( ) ) ;
14021424 let body = tcx. instance_mir ( instance. def ) ;
@@ -1407,7 +1429,7 @@ fn collect_neighbours<'tcx>(
14071429fn collect_const_value < ' tcx > (
14081430 tcx : TyCtxt < ' tcx > ,
14091431 value : ConstValue < ' tcx > ,
1410- output : & mut Vec < Spanned < MonoItem < ' tcx > > > ,
1432+ output : & mut MonoItems < ' tcx > ,
14111433) {
14121434 match value {
14131435 ConstValue :: Scalar ( Scalar :: Ptr ( ptr, _size) ) => collect_miri ( tcx, ptr. provenance , output) ,
0 commit comments