Skip to content

Commit 13b7aa4

Browse files
committed
Auto merge of #108524 - Zoxc:node-backtrace, r=cjgillot
Optimize dep node backtrace and ignore fatal errors This attempts to optimize #91742 while also passing through fatal errors. r? `@cjgillot`
2 parents 356c651 + f48ff4a commit 13b7aa4

File tree

2 files changed

+64
-51
lines changed

2 files changed

+64
-51
lines changed

compiler/rustc_query_system/src/dep_graph/graph.rs

+46-47
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_data_structures::sharded::{self, Sharded};
66
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
77
use rustc_data_structures::steal::Steal;
88
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
9-
use rustc_data_structures::OnDrop;
109
use rustc_index::vec::IndexVec;
1110
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
1211
use smallvec::{smallvec, SmallVec};
@@ -54,6 +53,11 @@ impl From<DepNodeIndex> for QueryInvocationId {
5453
}
5554
}
5655

56+
pub struct MarkFrame<'a> {
57+
index: SerializedDepNodeIndex,
58+
parent: Option<&'a MarkFrame<'a>>,
59+
}
60+
5761
#[derive(PartialEq)]
5862
pub enum DepNodeColor {
5963
Red,
@@ -710,32 +714,26 @@ impl<K: DepKind> DepGraphData<K> {
710714
let prev_index = self.previous.node_to_index_opt(dep_node)?;
711715

712716
match self.colors.get(prev_index) {
713-
Some(DepNodeColor::Green(dep_node_index)) => return Some((prev_index, dep_node_index)),
714-
Some(DepNodeColor::Red) => return None,
715-
None => {}
717+
Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
718+
Some(DepNodeColor::Red) => None,
719+
None => {
720+
// This DepNode and the corresponding query invocation existed
721+
// in the previous compilation session too, so we can try to
722+
// mark it as green by recursively marking all of its
723+
// dependencies green.
724+
self.try_mark_previous_green(qcx, prev_index, &dep_node, None)
725+
.map(|dep_node_index| (prev_index, dep_node_index))
726+
}
716727
}
717-
718-
let backtrace = backtrace_printer(qcx.dep_context().sess(), self, prev_index);
719-
720-
// This DepNode and the corresponding query invocation existed
721-
// in the previous compilation session too, so we can try to
722-
// mark it as green by recursively marking all of its
723-
// dependencies green.
724-
let ret = self
725-
.try_mark_previous_green(qcx, prev_index, &dep_node)
726-
.map(|dep_node_index| (prev_index, dep_node_index));
727-
728-
// We succeeded, no backtrace.
729-
backtrace.disable();
730-
return ret;
731728
}
732729

733-
#[instrument(skip(self, qcx, parent_dep_node_index), level = "debug")]
730+
#[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")]
734731
fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
735732
&self,
736733
qcx: Qcx,
737734
parent_dep_node_index: SerializedDepNodeIndex,
738735
dep_node: &DepNode<K>,
736+
frame: Option<&MarkFrame<'_>>,
739737
) -> Option<()> {
740738
let dep_dep_node_color = self.colors.get(parent_dep_node_index);
741739
let dep_dep_node = &self.previous.index_to_node(parent_dep_node_index);
@@ -767,7 +765,8 @@ impl<K: DepKind> DepGraphData<K> {
767765
dep_dep_node, dep_dep_node.hash,
768766
);
769767

770-
let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node);
768+
let node_index =
769+
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
771770

772771
if node_index.is_some() {
773772
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
@@ -777,7 +776,7 @@ impl<K: DepKind> DepGraphData<K> {
777776

778777
// We failed to mark it green, so we try to force the query.
779778
debug!("trying to force dependency {dep_dep_node:?}");
780-
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) {
779+
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) {
781780
// The DepNode could not be forced.
782781
debug!("dependency {dep_dep_node:?} could not be forced");
783782
return None;
@@ -816,13 +815,16 @@ impl<K: DepKind> DepGraphData<K> {
816815
}
817816

818817
/// Try to mark a dep-node which existed in the previous compilation session as green.
819-
#[instrument(skip(self, qcx, prev_dep_node_index), level = "debug")]
818+
#[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")]
820819
fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
821820
&self,
822821
qcx: Qcx,
823822
prev_dep_node_index: SerializedDepNodeIndex,
824823
dep_node: &DepNode<K>,
824+
frame: Option<&MarkFrame<'_>>,
825825
) -> Option<DepNodeIndex> {
826+
let frame = MarkFrame { index: prev_dep_node_index, parent: frame };
827+
826828
#[cfg(not(parallel_compiler))]
827829
{
828830
debug_assert!(!self.dep_node_exists(dep_node));
@@ -837,10 +839,7 @@ impl<K: DepKind> DepGraphData<K> {
837839
let prev_deps = self.previous.edge_targets_from(prev_dep_node_index);
838840

839841
for &dep_dep_node_index in prev_deps {
840-
let backtrace = backtrace_printer(qcx.dep_context().sess(), self, dep_dep_node_index);
841-
let success = self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node);
842-
backtrace.disable();
843-
success?;
842+
self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?;
844843
}
845844

846845
// If we got here without hitting a `return` that means that all
@@ -1414,25 +1413,25 @@ impl DepNodeColorMap {
14141413
}
14151414
}
14161415

1417-
fn backtrace_printer<'a, K: DepKind>(
1418-
sess: &'a rustc_session::Session,
1419-
graph: &'a DepGraphData<K>,
1420-
node: SerializedDepNodeIndex,
1421-
) -> OnDrop<impl Fn() + 'a> {
1422-
OnDrop(
1423-
#[inline(never)]
1424-
#[cold]
1425-
move || {
1426-
let node = graph.previous.index_to_node(node);
1427-
// Do not try to rely on DepNode's Debug implementation, since it may panic.
1428-
let diag = rustc_errors::Diagnostic::new(
1429-
rustc_errors::Level::FailureNote,
1430-
&format!(
1431-
"encountered while trying to mark dependency green: {:?}({})",
1432-
node.kind, node.hash
1433-
),
1434-
);
1435-
sess.diagnostic().force_print_diagnostic(diag);
1436-
},
1437-
)
1416+
#[inline(never)]
1417+
#[cold]
1418+
pub(crate) fn print_markframe_trace<K: DepKind>(
1419+
graph: &DepGraph<K>,
1420+
frame: Option<&MarkFrame<'_>>,
1421+
) {
1422+
let data = graph.data.as_ref().unwrap();
1423+
1424+
eprintln!("there was a panic while trying to force a dep node");
1425+
eprintln!("try_mark_green dep node stack:");
1426+
1427+
let mut i = 0;
1428+
let mut current = frame;
1429+
while let Some(frame) = current {
1430+
let node = data.previous.index_to_node(frame.index);
1431+
eprintln!("#{i} {:?}", node);
1432+
current = frame.parent;
1433+
i += 1;
1434+
}
1435+
1436+
eprintln!("end of try_mark_green dep node stack");
14381437
}

compiler/rustc_query_system/src/dep_graph/mod.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ use rustc_data_structures::profiling::SelfProfilerRef;
1717
use rustc_serialize::{opaque::FileEncoder, Encodable};
1818
use rustc_session::Session;
1919

20-
use std::fmt;
2120
use std::hash::Hash;
21+
use std::{fmt, panic};
22+
23+
use self::graph::{print_markframe_trace, MarkFrame};
2224

2325
pub trait DepContext: Copy {
2426
type DepKind: self::DepKind;
@@ -53,11 +55,23 @@ pub trait DepContext: Copy {
5355
}
5456

5557
/// Try to force a dep node to execute and see if it's green.
56-
#[instrument(skip(self), level = "debug")]
57-
fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool {
58+
#[inline]
59+
#[instrument(skip(self, frame), level = "debug")]
60+
fn try_force_from_dep_node(
61+
self,
62+
dep_node: DepNode<Self::DepKind>,
63+
frame: Option<&MarkFrame<'_>>,
64+
) -> bool {
5865
let cb = self.dep_kind_info(dep_node.kind);
5966
if let Some(f) = cb.force_from_dep_node {
60-
f(self, dep_node);
67+
if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
68+
f(self, dep_node);
69+
})) {
70+
if !value.is::<rustc_errors::FatalErrorMarker>() {
71+
print_markframe_trace(self.dep_graph(), frame);
72+
}
73+
panic::resume_unwind(value)
74+
}
6175
true
6276
} else {
6377
false

0 commit comments

Comments
 (0)