2828#include " swift/Runtime/Mutex.h"
2929#include " swift/Strings.h"
3030#include " llvm/ADT/DenseMap.h"
31+ #include " llvm/ADT/DenseSet.h"
3132#include " llvm/ADT/Optional.h"
3233#include " llvm/ADT/PointerIntPair.h"
3334#include " llvm/ADT/PointerUnion.h"
@@ -195,9 +196,20 @@ namespace {
195196 };
196197} // end anonymous namespace
197198
199+ inline llvm::hash_code llvm::hash_value (StringRef S) {
200+ return hash_combine_range (S.begin (), S.end ());
201+ }
202+
198203struct TypeMetadataPrivateState {
199204 ConcurrentMap<NominalTypeDescriptorCacheEntry> NominalCache;
200205 ConcurrentReadableArray<TypeMetadataSection> SectionsToScan;
206+
207+ llvm::DenseMap<llvm::StringRef,
208+ llvm::SmallDenseSet<const ContextDescriptor *, 1 >>
209+ ContextDescriptorCache;
210+ size_t ConformanceDescriptorLastSectionScanned = 0 ;
211+ size_t TypeContextDescriptorLastSectionScanned = 0 ;
212+ Mutex ContextDescriptorCacheLock;
201213
202214 TypeMetadataPrivateState () {
203215 initializeTypeMetadataRecordLookup ();
@@ -214,6 +226,29 @@ _registerTypeMetadataRecords(TypeMetadataPrivateState &T,
214226 T.SectionsToScan .push_back (TypeMetadataSection{begin, end});
215227}
216228
229+ // / Iterate over type metadata sections starting from the given index.
230+ // / The index is updated to the current number of sections. Passing
231+ // / the same index to the next call will iterate over any sections that were
232+ // / added after the previous call.
233+ // /
234+ // / Takes a function to call for each section found. The two parameters are
235+ // / the start and end of the section.
236+ static void _forEachTypeMetadataSectionAfter (
237+ TypeMetadataPrivateState &T,
238+ size_t *start,
239+ const std::function<void (const TypeMetadataRecord *,
240+ const TypeMetadataRecord *)> &f) {
241+ auto snapshot = T.SectionsToScan .snapshot ();
242+ if (snapshot.Count > *start) {
243+ auto *begin = snapshot.begin () + *start;
244+ auto *end = snapshot.end ();
245+ for (auto *section = begin; section != end; section++) {
246+ f (section->Begin , section->End );
247+ }
248+ *start = snapshot.Count ;
249+ }
250+ }
251+
217252void swift::addImageTypeMetadataRecordBlockCallback (const void *records,
218253 uintptr_t recordsSize) {
219254 assert (recordsSize % sizeof (TypeMetadataRecord) == 0
@@ -603,6 +638,70 @@ _searchTypeMetadataRecords(TypeMetadataPrivateState &T,
603638 return nullptr ;
604639}
605640
641+ // Read ContextDescriptors for any loaded images that haven't already been
642+ // scanned, if any.
643+ static void
644+ _scanAdditionalContextDescriptors (TypeMetadataPrivateState &T) {
645+ _forEachTypeMetadataSectionAfter (
646+ T,
647+ &T.TypeContextDescriptorLastSectionScanned ,
648+ [&T](const TypeMetadataRecord *Begin,
649+ const TypeMetadataRecord *End) {
650+ for (const auto *record = Begin; record != End; record++) {
651+ if (auto ntd = record->getContextDescriptor ()) {
652+ if (auto type = llvm::dyn_cast<TypeContextDescriptor>(ntd)) {
653+ auto identity = ParsedTypeIdentity::parse (type);
654+ auto name = identity.getABIName ();
655+ T.ContextDescriptorCache [name].insert (type);
656+ }
657+ }
658+ }
659+ });
660+
661+ _forEachProtocolConformanceSectionAfter (
662+ &T.ConformanceDescriptorLastSectionScanned ,
663+ [&T](const ProtocolConformanceRecord *Begin,
664+ const ProtocolConformanceRecord *End) {
665+ for (const auto *record = Begin; record != End; record++) {
666+ if (auto ntd = record[0 ]->getTypeDescriptor ()) {
667+ if (auto type = llvm::dyn_cast<TypeContextDescriptor>(ntd)) {
668+ auto identity = ParsedTypeIdentity::parse (type);
669+ auto name = identity.getABIName ();
670+ T.ContextDescriptorCache [name].insert (type);
671+ }
672+ }
673+ }
674+ });
675+ }
676+
677+ // Search for a ContextDescriptor in the context descriptor cache matching the
678+ // given demangle node. Returns the found node, or nullptr if no match was
679+ // found.
680+ static llvm::SmallDenseSet<const ContextDescriptor *, 1 >
681+ _findContextDescriptorInCache (TypeMetadataPrivateState &T,
682+ Demangle::NodePointer node) {
683+ if (node->getNumChildren () < 2 )
684+ return { };
685+
686+ auto nameNode = node->getChild (1 );
687+
688+ // Declarations synthesized by the Clang importer get a small tag
689+ // string in addition to their name.
690+ if (nameNode->getKind () == Demangle::Node::Kind::RelatedEntityDeclName)
691+ nameNode = nameNode->getChild (1 );
692+
693+ if (nameNode->getKind () != Demangle::Node::Kind::Identifier)
694+ return { };
695+
696+ auto name = nameNode->getText ();
697+
698+ auto iter = T.ContextDescriptorCache .find (name);
699+ if (iter == T.ContextDescriptorCache .end ())
700+ return { };
701+
702+ return iter->getSecond ();
703+ }
704+
606705static const ContextDescriptor *
607706_findContextDescriptor (Demangle::NodePointer node,
608707 Demangle::Demangler &Dem) {
@@ -613,9 +712,14 @@ _findContextDescriptor(Demangle::NodePointer node,
613712 NodePointer symbolicNode = node;
614713 if (symbolicNode->getKind () == Node::Kind::Type)
615714 symbolicNode = symbolicNode->getChild (0 );
616- if (symbolicNode->getKind () == Node::Kind::TypeSymbolicReference)
715+ if (symbolicNode->getKind () == Node::Kind::TypeSymbolicReference) {
617716 return cast<TypeContextDescriptor>(
618717 (const ContextDescriptor *)symbolicNode->getIndex ());
718+ }
719+
720+ // Nothing to resolve if have a generic parameter.
721+ if (symbolicNode->getKind () == Node::Kind::DependentGenericParamType)
722+ return nullptr ;
619723
620724 StringRef mangledName =
621725 Demangle::mangleNode (node, ExpandResolvedSymbolicReferences (Dem), Dem);
@@ -625,8 +729,25 @@ _findContextDescriptor(Demangle::NodePointer node,
625729 if (auto Value = T.NominalCache .find (mangledName))
626730 return Value->getDescription ();
627731
732+ // Scan any newly loaded images for context descriptors, then try the context
733+ // descriptor cache. This must be done with the cache's lock held.
734+ llvm::SmallDenseSet<const ContextDescriptor *, 1 > cachedContexts;
735+ {
736+ ScopedLock guard (T.ContextDescriptorCacheLock );
737+ _scanAdditionalContextDescriptors (T);
738+ cachedContexts = _findContextDescriptorInCache (T, node);
739+ }
740+
741+ for (auto cachedContext : cachedContexts) {
742+ if (_contextDescriptorMatchesMangling (cachedContext, node)) {
743+ foundContext = cachedContext;
744+ break ;
745+ }
746+ }
747+
628748 // Check type metadata records
629- foundContext = _searchTypeMetadataRecords (T, node);
749+ if (!foundContext)
750+ foundContext = _searchTypeMetadataRecords (T, node);
630751
631752 // Check protocol conformances table. Note that this has no support for
632753 // resolving generic types yet.
0 commit comments