mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Optimize dep node backtrace and ignore fatal errors
This commit is contained in:
parent
501ad021b9
commit
8dd0f20ee6
@ -6,7 +6,6 @@ use rustc_data_structures::sharded::{self, Sharded};
|
|||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::steal::Steal;
|
use rustc_data_structures::steal::Steal;
|
||||||
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
|
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
|
||||||
use rustc_data_structures::OnDrop;
|
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
@ -54,6 +53,11 @@ impl From<DepNodeIndex> for QueryInvocationId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct MarkFrame<'a> {
|
||||||
|
index: SerializedDepNodeIndex,
|
||||||
|
parent: Option<&'a MarkFrame<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum DepNodeColor {
|
pub enum DepNodeColor {
|
||||||
Red,
|
Red,
|
||||||
@ -710,32 +714,26 @@ impl<K: DepKind> DepGraphData<K> {
|
|||||||
let prev_index = self.previous.node_to_index_opt(dep_node)?;
|
let prev_index = self.previous.node_to_index_opt(dep_node)?;
|
||||||
|
|
||||||
match self.colors.get(prev_index) {
|
match self.colors.get(prev_index) {
|
||||||
Some(DepNodeColor::Green(dep_node_index)) => return Some((prev_index, dep_node_index)),
|
Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
|
||||||
Some(DepNodeColor::Red) => return None,
|
Some(DepNodeColor::Red) => None,
|
||||||
None => {}
|
None => {
|
||||||
|
// This DepNode and the corresponding query invocation existed
|
||||||
|
// in the previous compilation session too, so we can try to
|
||||||
|
// mark it as green by recursively marking all of its
|
||||||
|
// dependencies green.
|
||||||
|
self.try_mark_previous_green(qcx, prev_index, &dep_node, None)
|
||||||
|
.map(|dep_node_index| (prev_index, dep_node_index))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let backtrace = backtrace_printer(qcx.dep_context().sess(), self, prev_index);
|
|
||||||
|
|
||||||
// This DepNode and the corresponding query invocation existed
|
|
||||||
// in the previous compilation session too, so we can try to
|
|
||||||
// mark it as green by recursively marking all of its
|
|
||||||
// dependencies green.
|
|
||||||
let ret = self
|
|
||||||
.try_mark_previous_green(qcx, prev_index, &dep_node)
|
|
||||||
.map(|dep_node_index| (prev_index, dep_node_index));
|
|
||||||
|
|
||||||
// We succeeded, no backtrace.
|
|
||||||
backtrace.disable();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, qcx, parent_dep_node_index), level = "debug")]
|
#[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")]
|
||||||
fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
|
fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
|
||||||
&self,
|
&self,
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
parent_dep_node_index: SerializedDepNodeIndex,
|
parent_dep_node_index: SerializedDepNodeIndex,
|
||||||
dep_node: &DepNode<K>,
|
dep_node: &DepNode<K>,
|
||||||
|
frame: Option<&MarkFrame<'_>>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let dep_dep_node_color = self.colors.get(parent_dep_node_index);
|
let dep_dep_node_color = self.colors.get(parent_dep_node_index);
|
||||||
let dep_dep_node = &self.previous.index_to_node(parent_dep_node_index);
|
let dep_dep_node = &self.previous.index_to_node(parent_dep_node_index);
|
||||||
@ -767,7 +765,8 @@ impl<K: DepKind> DepGraphData<K> {
|
|||||||
dep_dep_node, dep_dep_node.hash,
|
dep_dep_node, dep_dep_node.hash,
|
||||||
);
|
);
|
||||||
|
|
||||||
let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node);
|
let node_index =
|
||||||
|
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
|
||||||
|
|
||||||
if node_index.is_some() {
|
if node_index.is_some() {
|
||||||
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
|
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
|
||||||
@ -777,7 +776,7 @@ impl<K: DepKind> DepGraphData<K> {
|
|||||||
|
|
||||||
// We failed to mark it green, so we try to force the query.
|
// We failed to mark it green, so we try to force the query.
|
||||||
debug!("trying to force dependency {dep_dep_node:?}");
|
debug!("trying to force dependency {dep_dep_node:?}");
|
||||||
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) {
|
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, data, frame) {
|
||||||
// The DepNode could not be forced.
|
// The DepNode could not be forced.
|
||||||
debug!("dependency {dep_dep_node:?} could not be forced");
|
debug!("dependency {dep_dep_node:?} could not be forced");
|
||||||
return None;
|
return None;
|
||||||
@ -816,13 +815,16 @@ impl<K: DepKind> DepGraphData<K> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Try to mark a dep-node which existed in the previous compilation session as green.
|
/// Try to mark a dep-node which existed in the previous compilation session as green.
|
||||||
#[instrument(skip(self, qcx, prev_dep_node_index), level = "debug")]
|
#[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")]
|
||||||
fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
|
fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
|
||||||
&self,
|
&self,
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
prev_dep_node_index: SerializedDepNodeIndex,
|
prev_dep_node_index: SerializedDepNodeIndex,
|
||||||
dep_node: &DepNode<K>,
|
dep_node: &DepNode<K>,
|
||||||
|
frame: Option<&MarkFrame<'_>>,
|
||||||
) -> Option<DepNodeIndex> {
|
) -> Option<DepNodeIndex> {
|
||||||
|
let frame = MarkFrame { index: prev_dep_node_index, parent: frame };
|
||||||
|
|
||||||
#[cfg(not(parallel_compiler))]
|
#[cfg(not(parallel_compiler))]
|
||||||
{
|
{
|
||||||
debug_assert!(!self.dep_node_exists(dep_node));
|
debug_assert!(!self.dep_node_exists(dep_node));
|
||||||
@ -837,10 +839,7 @@ impl<K: DepKind> DepGraphData<K> {
|
|||||||
let prev_deps = self.previous.edge_targets_from(prev_dep_node_index);
|
let prev_deps = self.previous.edge_targets_from(prev_dep_node_index);
|
||||||
|
|
||||||
for &dep_dep_node_index in prev_deps {
|
for &dep_dep_node_index in prev_deps {
|
||||||
let backtrace = backtrace_printer(qcx.dep_context().sess(), self, dep_dep_node_index);
|
self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?;
|
||||||
let success = self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node);
|
|
||||||
backtrace.disable();
|
|
||||||
success?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got here without hitting a `return` that means that all
|
// If we got here without hitting a `return` that means that all
|
||||||
@ -1414,25 +1413,24 @@ impl DepNodeColorMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn backtrace_printer<'a, K: DepKind>(
|
#[inline(never)]
|
||||||
sess: &'a rustc_session::Session,
|
#[cold]
|
||||||
graph: &'a DepGraphData<K>,
|
pub(crate) fn print_markframe_trace<K: DepKind>(
|
||||||
node: SerializedDepNodeIndex,
|
graph: &DepGraphData<K>,
|
||||||
) -> OnDrop<impl Fn() + 'a> {
|
frame: Option<&MarkFrame<'_>>,
|
||||||
OnDrop(
|
) {
|
||||||
#[inline(never)]
|
eprintln!("there was a panic while trying to force a dep node");
|
||||||
#[cold]
|
eprintln!("try_mark_green dep node stack:");
|
||||||
move || {
|
|
||||||
let node = graph.previous.index_to_node(node);
|
let mut i = 0;
|
||||||
|
let mut current = frame;
|
||||||
|
while let Some(frame) = current {
|
||||||
// Do not try to rely on DepNode's Debug implementation, since it may panic.
|
// Do not try to rely on DepNode's Debug implementation, since it may panic.
|
||||||
let diag = rustc_errors::Diagnostic::new(
|
let node = graph.previous.index_to_node(frame.index);
|
||||||
rustc_errors::Level::FailureNote,
|
eprintln!("#{i} {:?} ({})", node.kind, node.hash);
|
||||||
&format!(
|
current = frame.parent;
|
||||||
"encountered while trying to mark dependency green: {:?}({})",
|
i += 1;
|
||||||
node.kind, node.hash
|
}
|
||||||
),
|
|
||||||
);
|
eprintln!("end of try_mark_green dep node stack");
|
||||||
sess.diagnostic().force_print_diagnostic(diag);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,10 @@ use rustc_data_structures::profiling::SelfProfilerRef;
|
|||||||
use rustc_serialize::{opaque::FileEncoder, Encodable};
|
use rustc_serialize::{opaque::FileEncoder, Encodable};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::{fmt, panic};
|
||||||
|
|
||||||
|
use self::graph::{print_markframe_trace, DepGraphData, MarkFrame};
|
||||||
|
|
||||||
pub trait DepContext: Copy {
|
pub trait DepContext: Copy {
|
||||||
type DepKind: self::DepKind;
|
type DepKind: self::DepKind;
|
||||||
@ -53,11 +55,24 @@ pub trait DepContext: Copy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Try to force a dep node to execute and see if it's green.
|
/// Try to force a dep node to execute and see if it's green.
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[inline]
|
||||||
fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool {
|
#[instrument(skip(self, graph, frame), level = "debug")]
|
||||||
|
fn try_force_from_dep_node(
|
||||||
|
self,
|
||||||
|
dep_node: DepNode<Self::DepKind>,
|
||||||
|
graph: &DepGraphData<Self::DepKind>,
|
||||||
|
frame: Option<&MarkFrame<'_>>,
|
||||||
|
) -> bool {
|
||||||
let cb = self.dep_kind_info(dep_node.kind);
|
let cb = self.dep_kind_info(dep_node.kind);
|
||||||
if let Some(f) = cb.force_from_dep_node {
|
if let Some(f) = cb.force_from_dep_node {
|
||||||
f(self, dep_node);
|
if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||||
|
f(self, dep_node);
|
||||||
|
})) {
|
||||||
|
if !value.is::<rustc_errors::FatalErrorMarker>() {
|
||||||
|
print_markframe_trace(graph, frame);
|
||||||
|
}
|
||||||
|
panic::resume_unwind(value)
|
||||||
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
Loading…
Reference in New Issue
Block a user