Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove MonoItems. #112126

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 11 additions & 46 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,43 +226,7 @@ pub struct InliningMap<'tcx> {
inlines: GrowableBitSet<usize>,
}

/// Struct to store mono items in each collecting and if they should
/// be inlined. We call `instantiation_mode` to get their inlining
/// status when inserting new elements, which avoids calling it in
/// `inlining_map.lock_mut()`. See the `collect_items_rec` implementation
/// below.
struct MonoItems<'tcx> {
// If this is false, we do not need to compute whether items
// will need to be inlined.
compute_inlining: bool,

// The TyCtxt used to determine whether the a item should
// be inlined.
tcx: TyCtxt<'tcx>,

// The collected mono items. The bool field in each element
// indicates whether this element should be inlined.
items: Vec<(Spanned<MonoItem<'tcx>>, bool /*inlined*/)>,
}

impl<'tcx> MonoItems<'tcx> {
#[inline]
fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
self.extend([item]);
}

#[inline]
fn extend<T: IntoIterator<Item = Spanned<MonoItem<'tcx>>>>(&mut self, iter: T) {
self.items.extend(iter.into_iter().map(|mono_item| {
let inlined = if !self.compute_inlining {
false
} else {
mono_item.node.instantiation_mode(self.tcx) == InstantiationMode::LocalCopy
};
(mono_item, inlined)
}))
}
}
type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;

impl<'tcx> InliningMap<'tcx> {
fn new() -> InliningMap<'tcx> {
Expand All @@ -275,8 +239,9 @@ impl<'tcx> InliningMap<'tcx> {

fn record_accesses<'a>(
&mut self,
tcx: TyCtxt<'tcx>,
source: MonoItem<'tcx>,
new_targets: &'a [(Spanned<MonoItem<'tcx>>, bool)],
new_targets: &'a [Spanned<MonoItem<'tcx>>],
) where
'tcx: 'a,
{
Expand All @@ -287,9 +252,10 @@ impl<'tcx> InliningMap<'tcx> {
self.targets.reserve(new_items_count);
self.inlines.ensure(new_items_count_total);

for (i, (Spanned { node: mono_item, .. }, inlined)) in new_targets.into_iter().enumerate() {
for (i, Spanned { node: mono_item, .. }) in new_targets.into_iter().enumerate() {
self.targets.push(*mono_item);
if *inlined {
let is_inlined = mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy;
Copy link
Member

@SparrowLii SparrowLii May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key lies in the cost of calling instantiation_mode. Calling it within the lock will increase the locking time. It's not clear to me that if this has a noticeable effect on the efficiency of monomorphization. cc @Zoxc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment was added in #67756. Reviewers asked for more explanation in comments, but the PR author refused. It seems like it was for a deadlock. I ran the ui tests with the parallel front-end enabled without problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#112128 is an alternative approach that avoids the whole locking issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instantiation_mode uses queries so it could potentially invoke a lot of the compiler (including the query deadlock handler). I'm not confident this is unproblematic here (ignoring the performance reasons to not do it). I'd rather keep code inside locks small and predictable.

if is_inlined {
self.inlines.insert(i + start_index);
}
}
Expand Down Expand Up @@ -367,7 +333,7 @@ pub fn collect_crate_mono_items(
#[instrument(skip(tcx, mode), level = "debug")]
fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
debug!("collecting roots");
let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
let mut roots = Vec::new();

{
let entry_fn = tcx.entry_fn(());
Expand All @@ -393,9 +359,8 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
// whose predicates hold. Luckily, items that aren't instantiable
// can't actually be used, so we can just skip codegenning them.
roots
.items
.into_iter()
.filter_map(|(Spanned { node: mono_item, .. }, _)| {
.filter_map(|Spanned { node: mono_item, .. }| {
mono_item.is_instantiable(tcx).then_some(mono_item)
})
.collect()
Expand All @@ -417,7 +382,7 @@ fn collect_items_rec<'tcx>(
return;
}

let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
let mut neighbors = Vec::new();
let recursion_depth_reset;

//
Expand Down Expand Up @@ -542,9 +507,9 @@ fn collect_items_rec<'tcx>(
formatted_item,
});
}
inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
inlining_map.lock_mut().record_accesses(tcx, starting_point.node, &neighbors);

for (neighbour, _) in neighbors.items {
for neighbour in neighbors {
collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
}

Expand Down