Optimize Trace
.
`Trace::FromOutlivesConstraint` contains an `OutlivesConstraint`, which is 72 bytes. Lots of these are created but never used. This commit splits `Trace::FromOutlivesConstraint` into three new variants: `FromVanilla`, `FromStatic`, `FromMember`. Each of these contains just enough data to construct an `OutlivesConstraint`, if necessary. This reduces the size of `Trace` from 72 bytes to 16 bytes. All this avoids some memory traffic.
This commit is contained in:
parent
afc5e1fba5
commit
9a0513ad71
1 changed files with 51 additions and 36 deletions
|
@ -311,9 +311,11 @@ enum RegionRelationCheckResult {
|
|||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
enum Trace<'tcx> {
|
||||
enum Trace<'a, 'tcx> {
|
||||
StartRegion,
|
||||
FromOutlivesConstraint(OutlivesConstraint<'tcx>),
|
||||
FromGraph(&'a OutlivesConstraint<'tcx>),
|
||||
FromStatic(RegionVid),
|
||||
FromMember(RegionVid, RegionVid, Span),
|
||||
NotVisited,
|
||||
}
|
||||
|
||||
|
@ -1764,6 +1766,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
|
||||
context[from_region] = Trace::StartRegion;
|
||||
|
||||
let fr_static = self.universal_regions().fr_static;
|
||||
|
||||
// Use a deque so that we do a breadth-first search. We will
|
||||
// stop at the first match, which ought to be the shortest
|
||||
// path (fewest constraints).
|
||||
|
@ -1783,13 +1787,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
if target_test(r) {
|
||||
let mut result = vec![];
|
||||
let mut p = r;
|
||||
// This loop is cold and runs at the end, which is why we delay
|
||||
// `OutlivesConstraint` construction until now.
|
||||
loop {
|
||||
match context[p].clone() {
|
||||
Trace::NotVisited => {
|
||||
bug!("found unvisited region {:?} on path to {:?}", p, r)
|
||||
match context[p] {
|
||||
Trace::FromGraph(c) => {
|
||||
p = c.sup;
|
||||
result.push(*c);
|
||||
}
|
||||
|
||||
Trace::FromOutlivesConstraint(c) => {
|
||||
Trace::FromStatic(sub) => {
|
||||
let c = OutlivesConstraint {
|
||||
sup: fr_static,
|
||||
sub,
|
||||
locations: Locations::All(DUMMY_SP),
|
||||
span: DUMMY_SP,
|
||||
category: ConstraintCategory::Internal,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
};
|
||||
p = c.sup;
|
||||
result.push(c);
|
||||
}
|
||||
|
||||
Trace::FromMember(sup, sub, span) => {
|
||||
let c = OutlivesConstraint {
|
||||
sup,
|
||||
sub,
|
||||
locations: Locations::All(span),
|
||||
span,
|
||||
category: ConstraintCategory::OpaqueType,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
};
|
||||
p = c.sup;
|
||||
result.push(c);
|
||||
}
|
||||
|
@ -1798,6 +1828,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
result.reverse();
|
||||
return Some((result, r));
|
||||
}
|
||||
|
||||
Trace::NotVisited => {
|
||||
bug!("found unvisited region {:?} on path to {:?}", p, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1808,33 +1842,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
// A constraint like `'r: 'x` can come from our constraint
|
||||
// graph.
|
||||
let fr_static = self.universal_regions().fr_static;
|
||||
|
||||
// Always inline this closure because it can be hot.
|
||||
let mut handle_constraint = #[inline(always)]
|
||||
|constraint: &OutlivesConstraint<'tcx>| {
|
||||
debug_assert_eq!(constraint.sup, r);
|
||||
let sub_region = constraint.sub;
|
||||
if let Trace::NotVisited = context[sub_region] {
|
||||
context[sub_region] = Trace::FromOutlivesConstraint(*constraint);
|
||||
deque.push_back(sub_region);
|
||||
let mut handle_trace = #[inline(always)]
|
||||
|sub, trace| {
|
||||
if let Trace::NotVisited = context[sub] {
|
||||
context[sub] = trace;
|
||||
deque.push_back(sub);
|
||||
}
|
||||
};
|
||||
|
||||
// If this is the `'static` region and the graph's direction is normal, then set up the
|
||||
// Edges iterator to return all regions (#53178).
|
||||
if r == fr_static && self.constraint_graph.is_normal() {
|
||||
for next_static_idx in self.constraint_graph.outgoing_edges_from_static() {
|
||||
let constraint = OutlivesConstraint {
|
||||
sup: fr_static,
|
||||
sub: next_static_idx,
|
||||
locations: Locations::All(DUMMY_SP),
|
||||
span: DUMMY_SP,
|
||||
category: ConstraintCategory::Internal,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
};
|
||||
handle_constraint(&constraint);
|
||||
for sub in self.constraint_graph.outgoing_edges_from_static() {
|
||||
handle_trace(sub, Trace::FromStatic(sub));
|
||||
}
|
||||
} else {
|
||||
let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints);
|
||||
|
@ -1844,7 +1866,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
debug!("Ignoring illegal universe constraint: {constraint:?}");
|
||||
continue;
|
||||
}
|
||||
handle_constraint(constraint);
|
||||
debug_assert_eq!(constraint.sup, r);
|
||||
handle_trace(constraint.sub, Trace::FromGraph(constraint));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1852,17 +1875,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// were not part of the graph initially, so watch out for those.
|
||||
// (But they are extremely rare; this loop is very cold.)
|
||||
for constraint in self.applied_member_constraints(self.constraint_sccs.scc(r)) {
|
||||
let sub = constraint.min_choice;
|
||||
let p_c = &self.member_constraints[constraint.member_constraint_index];
|
||||
let constraint = OutlivesConstraint {
|
||||
sup: r,
|
||||
sub: constraint.min_choice,
|
||||
locations: Locations::All(p_c.definition_span),
|
||||
span: p_c.definition_span,
|
||||
category: ConstraintCategory::OpaqueType,
|
||||
variance_info: ty::VarianceDiagInfo::default(),
|
||||
from_closure: false,
|
||||
};
|
||||
handle_constraint(&constraint);
|
||||
handle_trace(sub, Trace::FromMember(r, sub, p_c.definition_span));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue