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)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
enum Trace<'tcx> {
|
enum Trace<'a, 'tcx> {
|
||||||
StartRegion,
|
StartRegion,
|
||||||
FromOutlivesConstraint(OutlivesConstraint<'tcx>),
|
FromGraph(&'a OutlivesConstraint<'tcx>),
|
||||||
|
FromStatic(RegionVid),
|
||||||
|
FromMember(RegionVid, RegionVid, Span),
|
||||||
NotVisited,
|
NotVisited,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1764,6 +1766,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
|
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
|
||||||
context[from_region] = Trace::StartRegion;
|
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
|
// Use a deque so that we do a breadth-first search. We will
|
||||||
// stop at the first match, which ought to be the shortest
|
// stop at the first match, which ought to be the shortest
|
||||||
// path (fewest constraints).
|
// path (fewest constraints).
|
||||||
|
@ -1783,13 +1787,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
if target_test(r) {
|
if target_test(r) {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let mut p = r;
|
let mut p = r;
|
||||||
|
// This loop is cold and runs at the end, which is why we delay
|
||||||
|
// `OutlivesConstraint` construction until now.
|
||||||
loop {
|
loop {
|
||||||
match context[p].clone() {
|
match context[p] {
|
||||||
Trace::NotVisited => {
|
Trace::FromGraph(c) => {
|
||||||
bug!("found unvisited region {:?} on path to {:?}", p, r)
|
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;
|
p = c.sup;
|
||||||
result.push(c);
|
result.push(c);
|
||||||
}
|
}
|
||||||
|
@ -1798,6 +1828,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
result.reverse();
|
result.reverse();
|
||||||
return Some((result, r));
|
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
|
// A constraint like `'r: 'x` can come from our constraint
|
||||||
// graph.
|
// graph.
|
||||||
let fr_static = self.universal_regions().fr_static;
|
|
||||||
|
|
||||||
// Always inline this closure because it can be hot.
|
// Always inline this closure because it can be hot.
|
||||||
let mut handle_constraint = #[inline(always)]
|
let mut handle_trace = #[inline(always)]
|
||||||
|constraint: &OutlivesConstraint<'tcx>| {
|
|sub, trace| {
|
||||||
debug_assert_eq!(constraint.sup, r);
|
if let Trace::NotVisited = context[sub] {
|
||||||
let sub_region = constraint.sub;
|
context[sub] = trace;
|
||||||
if let Trace::NotVisited = context[sub_region] {
|
deque.push_back(sub);
|
||||||
context[sub_region] = Trace::FromOutlivesConstraint(*constraint);
|
|
||||||
deque.push_back(sub_region);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// If this is the `'static` region and the graph's direction is normal, then set up the
|
// If this is the `'static` region and the graph's direction is normal, then set up the
|
||||||
// Edges iterator to return all regions (#53178).
|
// Edges iterator to return all regions (#53178).
|
||||||
if r == fr_static && self.constraint_graph.is_normal() {
|
if r == fr_static && self.constraint_graph.is_normal() {
|
||||||
for next_static_idx in self.constraint_graph.outgoing_edges_from_static() {
|
for sub in self.constraint_graph.outgoing_edges_from_static() {
|
||||||
let constraint = OutlivesConstraint {
|
handle_trace(sub, Trace::FromStatic(sub));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints);
|
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:?}");
|
debug!("Ignoring illegal universe constraint: {constraint:?}");
|
||||||
continue;
|
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.
|
// were not part of the graph initially, so watch out for those.
|
||||||
// (But they are extremely rare; this loop is very cold.)
|
// (But they are extremely rare; this loop is very cold.)
|
||||||
for constraint in self.applied_member_constraints(self.constraint_sccs.scc(r)) {
|
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 p_c = &self.member_constraints[constraint.member_constraint_index];
|
||||||
let constraint = OutlivesConstraint {
|
handle_trace(sub, Trace::FromMember(r, sub, p_c.definition_span));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue