@@ -76,6 +76,10 @@ STATISTIC(NumArchetypeAnchorCacheHits,
76
76
" # of hits in the archetype anchor cache" );
77
77
STATISTIC (NumArchetypeAnchorCacheMisses,
78
78
" # of misses in the archetype anchor cache" );
79
+ STATISTIC (NumNestedTypeCacheHits,
80
+ " # of hits in the equivalence class nested type cache" );
81
+ STATISTIC (NumNestedTypeCacheMisses,
82
+ " # of misses in the equivalence class nested type cache" );
79
83
STATISTIC (NumProcessDelayedRequirements,
80
84
" # of times we process delayed requirements" );
81
85
STATISTIC (NumProcessDelayedRequirementsUnchanged,
@@ -1585,6 +1589,38 @@ static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
1585
1589
TypeDecl *EquivalenceClass::lookupNestedType (
1586
1590
Identifier name,
1587
1591
SmallVectorImpl<TypeDecl *> *otherConcreteTypes) {
1592
+ // Populates the result structures from the given cache entry.
1593
+ auto populateResult = [&](const CachedNestedType &cache) -> TypeDecl * {
1594
+ if (otherConcreteTypes)
1595
+ otherConcreteTypes->clear ();
1596
+
1597
+ // If there aren't any types in the cache, we're done.
1598
+ if (cache.types .empty ()) return nullptr ;
1599
+
1600
+ // The first type in the cache is always the final result.
1601
+ // Collect the rest in the concrete-declarations list, if needed.
1602
+ if (otherConcreteTypes) {
1603
+ for (auto type : ArrayRef<TypeDecl *>(cache.types ).slice (1 )) {
1604
+ otherConcreteTypes->push_back (type);
1605
+ }
1606
+ }
1607
+
1608
+ return cache.types .front ();
1609
+ };
1610
+
1611
+ // If we have a cached value that is up-to-date, use that.
1612
+ auto cached = nestedTypeNameCache.find (name);
1613
+ if (cached != nestedTypeNameCache.end () &&
1614
+ cached->second .numConformancesPresent == conformsTo.size () &&
1615
+ (!superclass ||
1616
+ cached->second .superclassPresent == superclass->getCanonicalType ())) {
1617
+ ++NumNestedTypeCacheHits;
1618
+ return populateResult (cached->second );
1619
+ }
1620
+
1621
+ // Cache miss; go compute the result.
1622
+ ++NumNestedTypeCacheMisses;
1623
+
1588
1624
// Look for types with the given name in protocols that we know about.
1589
1625
AssociatedTypeDecl *bestAssocType = nullptr ;
1590
1626
SmallVector<TypeDecl *, 4 > concreteDecls;
@@ -1653,34 +1689,32 @@ TypeDecl *EquivalenceClass::lookupNestedType(
1653
1689
}
1654
1690
}
1655
1691
1656
- // If we have an associated type, that's our result.
1692
+ // Form the new cache entry.
1693
+ CachedNestedType entry;
1694
+ entry.numConformancesPresent = conformsTo.size ();
1695
+ entry.superclassPresent =
1696
+ superclass ? superclass->getCanonicalType () : CanType ();
1657
1697
if (bestAssocType) {
1658
- // Populate the list of concrete types, if requested.
1659
- if (otherConcreteTypes)
1660
- otherConcreteTypes->assign (concreteDecls.begin (), concreteDecls.end ());
1661
-
1662
- return bestAssocType;
1663
- }
1664
-
1665
- // If there were no concrete types either, lookup failed.
1666
- if (concreteDecls.empty ())
1667
- return nullptr ;
1668
-
1669
- // Find the best concrete type.
1670
- auto bestConcreteTypeIter =
1671
- std::min_element (concreteDecls.begin (), concreteDecls.end (),
1672
- [](TypeDecl *type1, TypeDecl *type2) {
1673
- return TypeDecl::compare (type1, type2) < 0 ;
1674
- });
1698
+ entry.types .push_back (bestAssocType);
1699
+ entry.types .insert (entry.types .end (),
1700
+ concreteDecls.begin (), concreteDecls.end ());
1701
+ } else if (!concreteDecls.empty ()) {
1702
+ // Find the best concrete type.
1703
+ auto bestConcreteTypeIter =
1704
+ std::min_element (concreteDecls.begin (), concreteDecls.end (),
1705
+ [](TypeDecl *type1, TypeDecl *type2) {
1706
+ return TypeDecl::compare (type1, type2) < 0 ;
1707
+ });
1675
1708
1676
- // If were asked to provide all of the concrete types, do so now.
1677
- if (otherConcreteTypes) {
1678
- otherConcreteTypes->assign (concreteDecls.begin (), bestConcreteTypeIter);
1679
- otherConcreteTypes->insert (otherConcreteTypes->end (),
1680
- bestConcreteTypeIter + 1 , concreteDecls.end ());
1709
+ // Put the best concrete type first; the rest will follow.
1710
+ entry.types .push_back (*bestConcreteTypeIter);
1711
+ entry.types .insert (entry.types .end (),
1712
+ concreteDecls.begin (), bestConcreteTypeIter);
1713
+ entry.types .insert (entry.types .end (),
1714
+ bestConcreteTypeIter + 1 , concreteDecls.end ());
1681
1715
}
1682
1716
1683
- return *bestConcreteTypeIter ;
1717
+ return populateResult ((nestedTypeNameCache[name] = std::move (entry))) ;
1684
1718
}
1685
1719
1686
1720
void EquivalenceClass::dump (llvm::raw_ostream &out) const {
0 commit comments