Skip to content

Commit 1ab9893

Browse files
committed
Auto merge of #97168 - SparrowLii:accesses, r=cjgillot
omit `record_accesses` function when collecting `MonoItem`s This PR fixes the FIXME in the impl of `record_accesses` function. [Edit] We can call `instantiation_mode` when push the `MonoItem` into `neighbors`. This avoids extra local variables `accesses: SmallVec<[_; 128]>`
2 parents 9e26dc7 + 480e603 commit 1ab9893

File tree

1 file changed

+66
-44
lines changed

1 file changed

+66
-44
lines changed

compiler/rustc_monomorphize/src/collector.rs

+66-44
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
201201
use rustc_session::Limit;
202202
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
203203
use rustc_target::abi::Size;
204-
use smallvec::SmallVec;
205204
use std::iter;
206205
use std::ops::Range;
207206
use 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+
229266
impl<'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.
322365
fn 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>) {
627653
struct 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>(
11591185
struct 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 {
13051331
fn 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>(
13961418
fn 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>(
14071429
fn 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

Comments
 (0)