Auto merge of #64627 - nnethercote:ObligForest-even-more, r=nikomatsakis
Even more `ObligationForest` improvements Following on from #64545, more speed and readability improvements. r? @nikomatsakis
This commit is contained in:
commit
c7bc0bf82f
6 changed files with 85 additions and 60 deletions
|
|
@ -1600,8 +1600,8 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
|
|||
|
||||
// `resolver.shallow_resolve_changed(ty)` is equivalent to
|
||||
// `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
|
||||
// inlined, despite being large, because it has a single call site that is
|
||||
// extremely hot.
|
||||
// inlined, despite being large, because it has only two call sites that
|
||||
// are extremely hot.
|
||||
#[inline(always)]
|
||||
pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool {
|
||||
match typ.sty {
|
||||
|
|
@ -1609,20 +1609,21 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
|
|||
use self::type_variable::TypeVariableValue;
|
||||
|
||||
// See the comment in `shallow_resolve()`.
|
||||
match self.infcx.type_variables.borrow_mut().probe(v) {
|
||||
match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
|
||||
TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ,
|
||||
TypeVariableValue::Unknown { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => {
|
||||
match self.infcx.int_unification_table.borrow_mut().probe_value(v) {
|
||||
match self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v) {
|
||||
Some(v) => v.to_type(self.infcx.tcx) != typ,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => {
|
||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||
match self.infcx.float_unification_table.borrow_mut().probe_value(v) {
|
||||
Some(v) => v.to_type(self.infcx.tcx) != typ,
|
||||
None => false,
|
||||
|
|
|
|||
|
|
@ -234,7 +234,13 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||
/// Retrieves the type to which `vid` has been instantiated, if
|
||||
/// any.
|
||||
pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
||||
self.eq_relations.probe_value(vid)
|
||||
self.inlined_probe(vid)
|
||||
}
|
||||
|
||||
/// An always-inlined variant of `probe`, for very hot call sites.
|
||||
#[inline(always)]
|
||||
pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
||||
self.eq_relations.inlined_probe_value(vid)
|
||||
}
|
||||
|
||||
/// If `t` is a type-inference variable, and it has been
|
||||
|
|
|
|||
|
|
@ -256,29 +256,46 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
|||
&mut self,
|
||||
pending_obligation: &mut Self::Obligation,
|
||||
) -> ProcessResult<Self::Obligation, Self::Error> {
|
||||
// If we were stalled on some unresolved variables, first check
|
||||
// whether any of them have been resolved; if not, don't bother
|
||||
// doing more work yet
|
||||
if !pending_obligation.stalled_on.is_empty() {
|
||||
let mut changed = false;
|
||||
// This `for` loop was once a call to `all()`, but this lower-level
|
||||
// form was a perf win. See #64545 for details.
|
||||
for &ty in &pending_obligation.stalled_on {
|
||||
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
// If we were stalled on some unresolved variables, first check whether
|
||||
// any of them have been resolved; if not, don't bother doing more work
|
||||
// yet.
|
||||
let change = match pending_obligation.stalled_on.len() {
|
||||
// Match arms are in order of frequency, which matters because this
|
||||
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
||||
1 => {
|
||||
let ty = pending_obligation.stalled_on[0];
|
||||
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty)
|
||||
}
|
||||
if !changed {
|
||||
debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
|
||||
self.selcx.infcx()
|
||||
.resolve_vars_if_possible(&pending_obligation.obligation),
|
||||
pending_obligation.stalled_on);
|
||||
return ProcessResult::Unchanged;
|
||||
0 => {
|
||||
// In this case we haven't changed, but wish to make a change.
|
||||
true
|
||||
}
|
||||
pending_obligation.stalled_on = vec![];
|
||||
_ => {
|
||||
// This `for` loop was once a call to `all()`, but this lower-level
|
||||
// form was a perf win. See #64545 for details.
|
||||
(|| {
|
||||
for &ty in &pending_obligation.stalled_on {
|
||||
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})()
|
||||
}
|
||||
};
|
||||
|
||||
if !change {
|
||||
debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
|
||||
self.selcx.infcx()
|
||||
.resolve_vars_if_possible(&pending_obligation.obligation),
|
||||
pending_obligation.stalled_on);
|
||||
return ProcessResult::Unchanged;
|
||||
}
|
||||
|
||||
// This part of the code is much colder.
|
||||
|
||||
pending_obligation.stalled_on.truncate(0);
|
||||
|
||||
let obligation = &mut pending_obligation.obligation;
|
||||
|
||||
if obligation.predicate.has_infer_types() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue