28
28
#include " swift/Runtime/Mutex.h"
29
29
#include " swift/Strings.h"
30
30
#include " llvm/ADT/DenseMap.h"
31
+ #include " llvm/ADT/DenseSet.h"
31
32
#include " llvm/ADT/Optional.h"
32
33
#include " llvm/ADT/PointerIntPair.h"
33
34
#include " llvm/ADT/PointerUnion.h"
@@ -195,9 +196,20 @@ namespace {
195
196
};
196
197
} // end anonymous namespace
197
198
199
+ inline llvm::hash_code llvm::hash_value (StringRef S) {
200
+ return hash_combine_range (S.begin (), S.end ());
201
+ }
202
+
198
203
struct TypeMetadataPrivateState {
199
204
ConcurrentMap<NominalTypeDescriptorCacheEntry> NominalCache;
200
205
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;
201
213
202
214
TypeMetadataPrivateState () {
203
215
initializeTypeMetadataRecordLookup ();
@@ -214,6 +226,29 @@ _registerTypeMetadataRecords(TypeMetadataPrivateState &T,
214
226
T.SectionsToScan .push_back (TypeMetadataSection{begin, end});
215
227
}
216
228
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
+
217
252
void swift::addImageTypeMetadataRecordBlockCallback (const void *records,
218
253
uintptr_t recordsSize) {
219
254
assert (recordsSize % sizeof (TypeMetadataRecord) == 0
@@ -603,6 +638,70 @@ _searchTypeMetadataRecords(TypeMetadataPrivateState &T,
603
638
return nullptr ;
604
639
}
605
640
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
+
606
705
static const ContextDescriptor *
607
706
_findContextDescriptor (Demangle::NodePointer node,
608
707
Demangle::Demangler &Dem) {
@@ -613,9 +712,14 @@ _findContextDescriptor(Demangle::NodePointer node,
613
712
NodePointer symbolicNode = node;
614
713
if (symbolicNode->getKind () == Node::Kind::Type)
615
714
symbolicNode = symbolicNode->getChild (0 );
616
- if (symbolicNode->getKind () == Node::Kind::TypeSymbolicReference)
715
+ if (symbolicNode->getKind () == Node::Kind::TypeSymbolicReference) {
617
716
return cast<TypeContextDescriptor>(
618
717
(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 ;
619
723
620
724
StringRef mangledName =
621
725
Demangle::mangleNode (node, ExpandResolvedSymbolicReferences (Dem), Dem);
@@ -625,8 +729,25 @@ _findContextDescriptor(Demangle::NodePointer node,
625
729
if (auto Value = T.NominalCache .find (mangledName))
626
730
return Value->getDescription ();
627
731
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
+
628
748
// Check type metadata records
629
- foundContext = _searchTypeMetadataRecords (T, node);
749
+ if (!foundContext)
750
+ foundContext = _searchTypeMetadataRecords (T, node);
630
751
631
752
// Check protocol conformances table. Note that this has no support for
632
753
// resolving generic types yet.
0 commit comments