Skip to content

Commit f778bde

Browse files
committed
Avoid repeated HashMap lookups in opt_normalize_projection_type.
There is a hot path through `opt_normalize_projection_type`: - `try_start` does a cache lookup (#1). - The result is a `NormalizedTy`. - There are no unresolved type vars, so we call `complete`. - `complete` does *another* cache lookup (#2), then calls `SnapshotMap::insert`. - `insert` does *another* cache lookup (#3), inserting the same value that's already in the cache. This patch optimizes this hot path by introducing `complete_normalized`, for use when the value is known in advance to be a `NormalizedTy`. It always avoids lookup #2. Furthermore, if the `NormalizedTy`'s obligations are empty (the common case), we know that lookup #3 would be a no-op, so we avoid it, while inserting a Noop into the `SnapshotMap`'s undo log.
1 parent 6fc409e commit f778bde

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/librustc/traits/project.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
596596
// Once we have inferred everything we need to know, we
597597
// can ignore the `obligations` from that point on.
598598
if !infcx.any_unresolved_type_vars(&ty.value) {
599-
infcx.projection_cache.borrow_mut().complete(cache_key);
599+
infcx.projection_cache.borrow_mut().complete_normalized(cache_key, &ty);
600600
ty.obligations = vec![];
601601
}
602602

@@ -1682,6 +1682,23 @@ impl<'tcx> ProjectionCache<'tcx> {
16821682
}));
16831683
}
16841684

1685+
/// A specialized version of `complete` for when the key's value is known
1686+
/// to be a NormalizedTy.
1687+
pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) {
1688+
// We want to insert `ty` with no obligations. If the existing value
1689+
// already has no obligations (as is common) we can use `insert_noop`
1690+
// to do a minimal amount of work -- the HashMap insertion is skipped,
1691+
// and minimal changes are made to the undo log.
1692+
if ty.obligations.is_empty() {
1693+
self.map.insert_noop();
1694+
} else {
1695+
self.map.insert(key, ProjectionCacheEntry::NormalizedTy(Normalized {
1696+
value: ty.value,
1697+
obligations: vec![]
1698+
}));
1699+
}
1700+
}
1701+
16851702
/// Indicates that trying to normalize `key` resulted in
16861703
/// ambiguity. No point in trying it again then until we gain more
16871704
/// type information (in which case, the "fully resolved" key will

src/librustc_data_structures/snapshot_map/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ impl<K, V> SnapshotMap<K, V>
6767
}
6868
}
6969

70+
pub fn insert_noop(&mut self) {
71+
if !self.undo_log.is_empty() {
72+
self.undo_log.push(UndoLog::Noop);
73+
}
74+
}
75+
7076
pub fn remove(&mut self, key: K) -> bool {
7177
match self.map.remove(&key) {
7278
Some(old_value) => {

0 commit comments

Comments
 (0)