@@ -53,7 +53,25 @@ _dyld_find_foreign_type_protocol_conformance(const void *protocol,
53
53
54
54
LLVM_ATTRIBUTE_WEAK
55
55
uint32_t _dyld_swift_optimizations_version (void );
56
- #endif
56
+
57
+ #if DYLD_FIND_PROTOCOL_ON_DISK_CONFORMANCE_DEFINED
58
+ // Redeclare these functions as weak as well.
59
+ LLVM_ATTRIBUTE_WEAK bool _dyld_has_preoptimized_swift_protocol_conformances (
60
+ const struct mach_header *mh);
61
+
62
+ LLVM_ATTRIBUTE_WEAK struct _dyld_protocol_conformance_result
63
+ _dyld_find_protocol_conformance_on_disk (const void *protocolDescriptor,
64
+ const void *metadataType,
65
+ const void *typeDescriptor,
66
+ uint32_t flags);
67
+
68
+ LLVM_ATTRIBUTE_WEAK struct _dyld_protocol_conformance_result
69
+ _dyld_find_foreign_type_protocol_conformance_on_disk (
70
+ const void *protocol, const char *foreignTypeIdentityStart,
71
+ size_t foreignTypeIdentityLength, uint32_t flags);
72
+ #endif // DYLD_FIND_PROTOCOL_ON_DISK_CONFORMANCE_DEFINED
73
+
74
+ #endif // __has_include(<mach-o/dyld_priv.h>)
57
75
58
76
// Set this to 1 to enable logging of calls to the dyld shared cache conformance
59
77
// table
@@ -411,19 +429,20 @@ struct ConformanceState {
411
429
uintptr_t dyldSharedCacheStart;
412
430
uintptr_t dyldSharedCacheEnd;
413
431
bool hasOverriddenImage;
414
- bool validateSharedCacheResults ;
432
+ bool validateDyldResults ;
415
433
416
- // Only populated when validateSharedCacheResults is enabled.
417
- ConcurrentReadableArray<ConformanceSection> SharedCacheSections ;
434
+ // Only populated when validateDyldResults is enabled.
435
+ ConcurrentReadableArray<ConformanceSection> DyldOptimizedSections ;
418
436
419
437
bool inSharedCache (const void *ptr) {
420
438
auto uintPtr = reinterpret_cast <uintptr_t >(ptr);
421
439
return dyldSharedCacheStart <= uintPtr && uintPtr < dyldSharedCacheEnd;
422
440
}
423
441
424
- bool sharedCacheOptimizationsActive () { return dyldSharedCacheStart != 0 ; }
442
+ bool dyldOptimizationsActive () { return dyldSharedCacheStart != 0 ; }
425
443
#else
426
- bool sharedCacheOptimizationsActive () { return false ; }
444
+ bool dyldOptimizationsActive () { return false ; }
445
+
427
446
#endif
428
447
429
448
ConformanceState () {
@@ -441,7 +460,7 @@ struct ConformanceState {
441
460
(uintptr_t )_dyld_get_shared_cache_range (&length);
442
461
dyldSharedCacheEnd =
443
462
dyldSharedCacheStart ? dyldSharedCacheStart + length : 0 ;
444
- validateSharedCacheResults = runtime::environment::
463
+ validateDyldResults = runtime::environment::
445
464
SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES ();
446
465
SHARED_CACHE_LOG (" Shared cache range is %#lx-%#lx" ,
447
466
dyldSharedCacheStart, dyldSharedCacheEnd);
@@ -557,10 +576,21 @@ void swift::addImageProtocolConformanceBlockCallbackUnsafe(
557
576
if (C.inSharedCache (conformances)) {
558
577
SHARED_CACHE_LOG (" Skipping conformances section %p in the shared cache" ,
559
578
conformances);
560
- if (C.validateSharedCacheResults )
561
- C.SharedCacheSections .push_back (
579
+ if (C.validateDyldResults )
580
+ C.DyldOptimizedSections .push_back (
581
+ ConformanceSection{conformances, conformancesSize});
582
+ return ;
583
+ #if DYLD_FIND_PROTOCOL_ON_DISK_CONFORMANCE_DEFINED
584
+ } else if (_dyld_has_preoptimized_swift_protocol_conformances (
585
+ reinterpret_cast <const mach_header *>(baseAddress))) {
586
+ // dyld may optimize images outside the shared cache. Skip those too.
587
+ SHARED_CACHE_LOG (" Skipping conformances section %p optimized by dyld" ,
588
+ conformances);
589
+ if (C.validateDyldResults )
590
+ C.DyldOptimizedSections .push_back (
562
591
ConformanceSection{conformances, conformancesSize});
563
592
return ;
593
+ #endif
564
594
} else {
565
595
SHARED_CACHE_LOG (
566
596
" Adding conformances section %p outside the shared cache" ,
@@ -705,18 +735,18 @@ namespace {
705
735
};
706
736
}
707
737
708
- static void validateSharedCacheResults (
738
+ static void validateDyldResults (
709
739
ConformanceState &C, const Metadata *type,
710
740
const ProtocolDescriptor *protocol,
711
741
const WitnessTable *dyldCachedWitnessTable,
712
742
const ProtocolConformanceDescriptor *dyldCachedConformanceDescriptor,
713
743
bool instantiateSuperclassMetadata) {
714
744
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
715
- if (!C.sharedCacheOptimizationsActive () || !C.validateSharedCacheResults )
745
+ if (!C.dyldOptimizationsActive () || !C.validateDyldResults )
716
746
return ;
717
747
718
748
llvm::SmallVector<const ProtocolConformanceDescriptor *, 8 > conformances;
719
- for (auto §ion : C.SharedCacheSections .snapshot ()) {
749
+ for (auto §ion : C.DyldOptimizedSections .snapshot ()) {
720
750
for (const auto &record : section) {
721
751
auto &descriptor = *record.get ();
722
752
if (descriptor.getProtocol () != protocol)
@@ -765,15 +795,61 @@ static void validateSharedCacheResults(
765
795
#endif
766
796
}
767
797
768
- // / Query the shared cache for a protocol conformance, if supported. The return
798
+ #if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
799
+ static _dyld_protocol_conformance_result getDyldSharedCacheConformance (
800
+ ConformanceState &C, const ProtocolDescriptor *protocol,
801
+ const ClassMetadata *objcClassMetadata,
802
+ const ContextDescriptor *description, llvm::StringRef foreignTypeIdentity) {
803
+ if (!foreignTypeIdentity.empty ()) {
804
+ SHARED_CACHE_LOG (
805
+ " _dyld_find_foreign_type_protocol_conformance(%p, %.*s, %zu)" , protocol,
806
+ (int )foreignTypeIdentity.size (), foreignTypeIdentity.data (),
807
+ foreignTypeIdentity.size ());
808
+ return _dyld_find_foreign_type_protocol_conformance (
809
+ protocol, foreignTypeIdentity.data (), foreignTypeIdentity.size ());
810
+ } else {
811
+ SHARED_CACHE_LOG (" _dyld_find_protocol_conformance(%p, %p, %p)" , protocol,
812
+ objcClassMetadata, description);
813
+ return _dyld_find_protocol_conformance (protocol, objcClassMetadata,
814
+ description);
815
+ }
816
+ }
817
+
818
+ static _dyld_protocol_conformance_result getDyldOnDiskConformance (
819
+ ConformanceState &C, const ProtocolDescriptor *protocol,
820
+ const ClassMetadata *objcClassMetadata,
821
+ const ContextDescriptor *description, llvm::StringRef foreignTypeIdentity) {
822
+ #if DYLD_FIND_PROTOCOL_ON_DISK_CONFORMANCE_DEFINED
823
+ if (&_dyld_find_foreign_type_protocol_conformance_on_disk &&
824
+ &_dyld_find_protocol_conformance_on_disk) {
825
+ if (!foreignTypeIdentity.empty ()) {
826
+ SHARED_CACHE_LOG (" _dyld_find_foreign_type_protocol_conformance_on_disk(%"
827
+ " p, %.*s, %zu, 0)" ,
828
+ protocol, (int )foreignTypeIdentity.size (),
829
+ foreignTypeIdentity.data (), foreignTypeIdentity.size ());
830
+ return _dyld_find_foreign_type_protocol_conformance_on_disk (
831
+ protocol, foreignTypeIdentity.data (), foreignTypeIdentity.size (), 0 );
832
+ } else {
833
+ SHARED_CACHE_LOG (" _dyld_find_protocol_conformance_on_disk(%p, %p, %p, 0)" ,
834
+ protocol, objcClassMetadata, description);
835
+ return _dyld_find_protocol_conformance_on_disk (
836
+ protocol, objcClassMetadata, description, 0 );
837
+ }
838
+ }
839
+ #endif
840
+ return {_dyld_protocol_conformance_result_kind_not_found, nullptr };
841
+ }
842
+ #endif
843
+
844
+ // / Query dyld for a protocol conformance, if supported. The return
769
845
// / value is a tuple consisting of the found witness table (if any), the found
770
846
// / conformance descriptor (if any), and a bool that's true if a failure is
771
847
// / definitive.
772
848
static std::tuple<const WitnessTable *, const ProtocolConformanceDescriptor *,
773
849
bool >
774
- findSharedCacheConformance (ConformanceState &C, const Metadata *type,
775
- const ProtocolDescriptor *protocol,
776
- bool instantiateSuperclassMetadata) {
850
+ findConformanceWithDyld (ConformanceState &C, const Metadata *type,
851
+ const ProtocolDescriptor *protocol,
852
+ bool instantiateSuperclassMetadata) {
777
853
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
778
854
const ContextDescriptor *description;
779
855
llvm::StringRef foreignTypeIdentity;
@@ -787,6 +863,21 @@ findSharedCacheConformance(ConformanceState &C, const Metadata *type,
787
863
typeName.data , protocol->Name .get ());
788
864
#endif
789
865
_dyld_protocol_conformance_result dyldResult;
866
+ if (C.scanSectionsBackwards ) {
867
+ // Search "on disk" first, then shared cache.
868
+ dyldResult = getDyldOnDiskConformance (C, protocol, objcClassMetadata,
869
+ description, foreignTypeIdentity);
870
+ if (dyldResult.kind == _dyld_protocol_conformance_result_kind_not_found)
871
+ dyldResult = getDyldSharedCacheConformance (
872
+ C, protocol, objcClassMetadata, description, foreignTypeIdentity);
873
+ } else {
874
+ // In normal operation, search the shared cache first.
875
+ dyldResult = getDyldSharedCacheConformance (
876
+ C, protocol, objcClassMetadata, description, foreignTypeIdentity);
877
+ if (dyldResult.kind == _dyld_protocol_conformance_result_kind_not_found)
878
+ dyldResult = getDyldOnDiskConformance (C, protocol, objcClassMetadata,
879
+ description, foreignTypeIdentity);
880
+ }
790
881
if (!foreignTypeIdentity.empty ()) {
791
882
SHARED_CACHE_LOG (
792
883
" _dyld_find_foreign_type_protocol_conformance(%p, %.*s, %zu)" , protocol,
@@ -876,14 +967,14 @@ swift_conformsToProtocolMaybeInstantiateSuperclasses(
876
967
877
968
// Search the shared cache tables for a conformance for this type, and for
878
969
// superclasses (if it's a class).
879
- if (C.sharedCacheOptimizationsActive ()) {
970
+ if (C.dyldOptimizationsActive ()) {
880
971
for (auto dyldSearchType : iterateMaybeIncompleteSuperclasses (
881
972
type, instantiateSuperclassMetadata)) {
882
973
bool definitiveFailure;
883
974
std::tie (dyldCachedWitnessTable, dyldCachedConformanceDescriptor,
884
975
definitiveFailure) =
885
- findSharedCacheConformance (C, dyldSearchType, protocol,
886
- instantiateSuperclassMetadata);
976
+ findConformanceWithDyld (C, dyldSearchType, protocol,
977
+ instantiateSuperclassMetadata);
887
978
888
979
if (definitiveFailure)
889
980
return {nullptr , false };
@@ -892,9 +983,9 @@ swift_conformsToProtocolMaybeInstantiateSuperclasses(
892
983
break ;
893
984
}
894
985
895
- validateSharedCacheResults (C, type, protocol, dyldCachedWitnessTable,
896
- dyldCachedConformanceDescriptor,
897
- instantiateSuperclassMetadata);
986
+ validateDyldResults (C, type, protocol, dyldCachedWitnessTable,
987
+ dyldCachedConformanceDescriptor,
988
+ instantiateSuperclassMetadata);
898
989
// Return a cached result if we got a witness table. We can't do this if
899
990
// scanSectionsBackwards is set, since a scanned conformance can override a
900
991
// cached result in that case.
0 commit comments