Skip to content

Commit 6e48053

Browse files
committed
Use iterators in error_at and process_cycle.
This makes the code a little faster, presumably because bounds checks aren't needed on `nodes` accesses. It requires making `scratch` a `RefCell`, which is not unreasonable.
1 parent e2492b7 commit 6e48053

File tree

1 file changed

+18
-16
lines changed
  • src/librustc_data_structures/obligation_forest

1 file changed

+18
-16
lines changed

src/librustc_data_structures/obligation_forest/mod.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use crate::fx::{FxHashMap, FxHashSet};
7676
use crate::indexed_vec::Idx;
7777
use crate::newtype_index;
7878

79-
use std::cell::Cell;
79+
use std::cell::{Cell, RefCell};
8080
use std::collections::hash_map::Entry;
8181
use std::fmt::Debug;
8282
use std::hash;
@@ -156,7 +156,9 @@ pub struct ObligationForest<O: ForestObligation> {
156156
/// comments in `process_obligation` for details.
157157
waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
158158

159-
scratch: Option<Vec<usize>>,
159+
/// A scratch vector reused in various operations, to avoid allocating new
160+
/// vectors.
161+
scratch: RefCell<Vec<usize>>,
160162

161163
obligation_tree_id_generator: ObligationTreeIdGenerator,
162164

@@ -265,7 +267,7 @@ impl<O: ForestObligation> ObligationForest<O> {
265267
nodes: vec![],
266268
done_cache: Default::default(),
267269
waiting_cache: Default::default(),
268-
scratch: Some(vec![]),
270+
scratch: RefCell::new(vec![]),
269271
obligation_tree_id_generator: (0..).map(ObligationTreeId),
270272
error_cache: Default::default(),
271273
}
@@ -345,8 +347,8 @@ impl<O: ForestObligation> ObligationForest<O> {
345347
/// Converts all remaining obligations to the given error.
346348
pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
347349
let mut errors = vec![];
348-
for i in 0..self.nodes.len() {
349-
if let NodeState::Pending = self.nodes[i].state.get() {
350+
for (i, node) in self.nodes.iter().enumerate() {
351+
if let NodeState::Pending = node.state.get() {
350352
let backtrace = self.error_at(i);
351353
errors.push(Error {
352354
error: error.clone(),
@@ -469,20 +471,20 @@ impl<O: ForestObligation> ObligationForest<O> {
469471
/// report all cycles between them. This should be called
470472
/// after `mark_as_waiting` marks all nodes with pending
471473
/// subobligations as NodeState::Waiting.
472-
fn process_cycles<P>(&mut self, processor: &mut P)
474+
fn process_cycles<P>(&self, processor: &mut P)
473475
where P: ObligationProcessor<Obligation=O>
474476
{
475-
let mut stack = self.scratch.take().unwrap();
477+
let mut stack = self.scratch.replace(vec![]);
476478
debug_assert!(stack.is_empty());
477479

478480
debug!("process_cycles()");
479481

480-
for i in 0..self.nodes.len() {
482+
for (i, node) in self.nodes.iter().enumerate() {
481483
// For rustc-benchmarks/inflate-0.1.0 this state test is extremely
482484
// hot and the state is almost always `Pending` or `Waiting`. It's
483485
// a win to handle the no-op cases immediately to avoid the cost of
484486
// the function call.
485-
match self.nodes[i].state.get() {
487+
match node.state.get() {
486488
NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {},
487489
_ => self.find_cycles_from_node(&mut stack, processor, i),
488490
}
@@ -491,7 +493,7 @@ impl<O: ForestObligation> ObligationForest<O> {
491493
debug!("process_cycles: complete");
492494

493495
debug_assert!(stack.is_empty());
494-
self.scratch = Some(stack);
496+
self.scratch.replace(stack);
495497
}
496498

497499
fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, i: usize)
@@ -525,8 +527,8 @@ impl<O: ForestObligation> ObligationForest<O> {
525527

526528
/// Returns a vector of obligations for `p` and all of its
527529
/// ancestors, putting them into the error state in the process.
528-
fn error_at(&mut self, mut i: usize) -> Vec<O> {
529-
let mut error_stack = self.scratch.take().unwrap();
530+
fn error_at(&self, mut i: usize) -> Vec<O> {
531+
let mut error_stack = self.scratch.replace(vec![]);
530532
let mut trace = vec![];
531533

532534
loop {
@@ -554,7 +556,7 @@ impl<O: ForestObligation> ObligationForest<O> {
554556
);
555557
}
556558

557-
self.scratch = Some(error_stack);
559+
self.scratch.replace(error_stack);
558560
trace
559561
}
560562

@@ -608,7 +610,7 @@ impl<O: ForestObligation> ObligationForest<O> {
608610
#[inline(never)]
609611
fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
610612
let nodes_len = self.nodes.len();
611-
let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
613+
let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]);
612614
node_rewrites.extend(0..nodes_len);
613615
let mut dead_nodes = 0;
614616

@@ -658,7 +660,7 @@ impl<O: ForestObligation> ObligationForest<O> {
658660
// No compression needed.
659661
if dead_nodes == 0 {
660662
node_rewrites.truncate(0);
661-
self.scratch = Some(node_rewrites);
663+
self.scratch.replace(node_rewrites);
662664
return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
663665
}
664666

@@ -682,7 +684,7 @@ impl<O: ForestObligation> ObligationForest<O> {
682684
self.apply_rewrites(&node_rewrites);
683685

684686
node_rewrites.truncate(0);
685-
self.scratch = Some(node_rewrites);
687+
self.scratch.replace(node_rewrites);
686688

687689
successful
688690
}

0 commit comments

Comments
 (0)