Skip to content

Commit 13a4bd4

Browse files
committed
perf: Merge done_cache and active_cache in ObligationForest
Removes one hash lookup (of two) in `register_obligation_at`.
1 parent 093241d commit 13a4bd4

File tree

1 file changed

+23
-46
lines changed
  • src/librustc_data_structures/obligation_forest

1 file changed

+23
-46
lines changed

src/librustc_data_structures/obligation_forest/mod.rs

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,10 @@ pub struct ObligationForest<O: ForestObligation> {
137137
/// significant, and space considerations are not important.
138138
nodes: Vec<Node<O>>,
139139

140-
/// A cache of predicates that have been successfully completed.
141-
done_cache: FxHashSet<O::Predicate>,
142-
143140
/// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
144141
/// its contents are not guaranteed to match those of `nodes`. See the
145142
/// comments in `process_obligation` for details.
146-
active_cache: FxHashMap<O::Predicate, usize>,
143+
active_cache: FxHashMap<O::Predicate, Option<usize>>,
147144

148145
/// A vector reused in compress(), to avoid allocating new vectors.
149146
node_rewrites: RefCell<Vec<usize>>,
@@ -283,7 +280,6 @@ impl<O: ForestObligation> ObligationForest<O> {
283280
pub fn new() -> ObligationForest<O> {
284281
ObligationForest {
285282
nodes: vec![],
286-
done_cache: Default::default(),
287283
active_cache: Default::default(),
288284
node_rewrites: RefCell::new(vec![]),
289285
obligation_tree_id_generator: (0..).map(ObligationTreeId),
@@ -305,13 +301,13 @@ impl<O: ForestObligation> ObligationForest<O> {
305301

306302
// Returns Err(()) if we already know this obligation failed.
307303
fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Result<(), ()> {
308-
if self.done_cache.contains(obligation.as_predicate()) {
309-
return Ok(());
310-
}
311-
312304
match self.active_cache.entry(obligation.as_predicate().clone()) {
313305
Entry::Occupied(o) => {
314-
let node = &mut self.nodes[*o.get()];
306+
let index = match o.get() {
307+
Some(index) => *index,
308+
None => return Ok(()), // Done!
309+
};
310+
let node = &mut self.nodes[index];
315311
if let Some(parent_index) = parent {
316312
// If the node is already in `active_cache`, it has already
317313
// had its chance to be marked with a parent. So if it's
@@ -340,7 +336,7 @@ impl<O: ForestObligation> ObligationForest<O> {
340336
Err(())
341337
} else {
342338
let new_index = self.nodes.len();
343-
v.insert(new_index);
339+
v.insert(Some(new_index));
344340
self.nodes.push(Node::new(parent, obligation, obligation_tree_id));
345341
Ok(())
346342
}
@@ -576,7 +572,7 @@ impl<O: ForestObligation> ObligationForest<O> {
576572
Some(rpos) => {
577573
// Cycle detected.
578574
processor.process_backedge(
579-
stack[rpos..].iter().map(GetObligation(&self.nodes)),
575+
stack[rpos..].iter().map(|i| &self.nodes[*i].obligation),
580576
PhantomData,
581577
);
582578
}
@@ -590,6 +586,7 @@ impl<O: ForestObligation> ObligationForest<O> {
590586
#[inline(never)]
591587
fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
592588
let orig_nodes_len = self.nodes.len();
589+
let remove_node_marker = orig_nodes_len + 1;
593590
let mut node_rewrites: Vec<_> = self.node_rewrites.replace(vec![]);
594591
debug_assert!(node_rewrites.is_empty());
595592
node_rewrites.extend(0..orig_nodes_len);
@@ -613,17 +610,6 @@ impl<O: ForestObligation> ObligationForest<O> {
613610
}
614611
}
615612
NodeState::Done => {
616-
// This lookup can fail because the contents of
617-
// `self.active_cache` are not guaranteed to match those of
618-
// `self.nodes`. See the comment in `process_obligation`
619-
// for more details.
620-
if let Some((predicate, _)) =
621-
self.active_cache.remove_entry(node.obligation.as_predicate())
622-
{
623-
self.done_cache.insert(predicate);
624-
} else {
625-
self.done_cache.insert(node.obligation.as_predicate().clone());
626-
}
627613
if do_completed == DoCompleted::Yes {
628614
// Extract the success stories.
629615
removed_done_obligations.push(node.obligation.clone());
@@ -637,7 +623,7 @@ impl<O: ForestObligation> ObligationForest<O> {
637623
// check against.
638624
self.active_cache.remove(node.obligation.as_predicate());
639625
self.insert_into_error_cache(index);
640-
node_rewrites[index] = orig_nodes_len;
626+
node_rewrites[index] = remove_node_marker;
641627
dead_nodes += 1;
642628
}
643629
NodeState::Success => unreachable!(),
@@ -658,6 +644,7 @@ impl<O: ForestObligation> ObligationForest<O> {
658644

659645
fn apply_rewrites(&mut self, node_rewrites: &[usize]) {
660646
let orig_nodes_len = node_rewrites.len();
647+
let remove_node_marker = orig_nodes_len + 1;
661648

662649
for node in &mut self.nodes {
663650
let mut i = 0;
@@ -678,31 +665,21 @@ impl<O: ForestObligation> ObligationForest<O> {
678665

679666
// This updating of `self.active_cache` is necessary because the
680667
// removal of nodes within `compress` can fail. See above.
681-
self.active_cache.retain(|_predicate, index| {
682-
let new_index = node_rewrites[*index];
683-
if new_index >= orig_nodes_len {
684-
false
668+
self.active_cache.retain(|_predicate, opt_index| {
669+
if let Some(index) = opt_index {
670+
let new_index = node_rewrites[*index];
671+
if new_index == orig_nodes_len {
672+
*opt_index = None;
673+
true
674+
} else if new_index == remove_node_marker {
675+
false
676+
} else {
677+
*index = new_index;
678+
true
679+
}
685680
} else {
686-
*index = new_index;
687681
true
688682
}
689683
});
690684
}
691685
}
692-
693-
// I need a Clone closure.
694-
#[derive(Clone)]
695-
struct GetObligation<'a, O>(&'a [Node<O>]);
696-
697-
impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> {
698-
type Output = &'a O;
699-
extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O {
700-
&self.0[*args.0].obligation
701-
}
702-
}
703-
704-
impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> {
705-
extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O {
706-
&self.0[*args.0].obligation
707-
}
708-
}

0 commit comments

Comments
 (0)