Skip to content

Commit 5193d76

Browse files
committed
[Runtime] Fixed shared cache protocol conformance lookup with subclasses.
Match the logic used in the non-shared-cache case, where we walk up the class hierarchy to find the class where the conformance actually applies. This is important in cases like: class Super<T> : Proto {} class Sub: Super<Int> {} Looking up the conformance `Sub: Proto` without this logic causes it to attempt to find the witness table for `Sub<Int>`, which fails. The correct logic looks up the witness table for `Super<Int>`. While we're in there, fix a bug in the shared cache validation code (std::find wasn't checked for failure correctly) and add a `SWIFT_DEBUG_ENABLE_SHARED_CACHE_PROTOCOL_CONFORMANCES` environment variable to allow us to turn the shared cache integration off at runtime. rdar://75431771
1 parent 29cfd3e commit 5193d76

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

stdlib/public/runtime/EnvironmentVariables.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ VARIABLE(SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES, bool, false,
5353
"Validate shared cache protocol conformance results against the "
5454
"lists of conformances in the shared cache images.")
5555

56+
VARIABLE(SWIFT_DEBUG_ENABLE_SHARED_CACHE_PROTOCOL_CONFORMANCES, bool, true,
57+
"Enable querying precomputed protocol conformances in the shared "
58+
"cache.")
59+
5660
#endif
5761

5862
#undef VARIABLE

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -303,25 +303,27 @@ struct ConformanceState {
303303

304304
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
305305
if (__builtin_available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)) {
306-
if (&_dyld_swift_optimizations_version) {
307-
if (_dyld_swift_optimizations_version() ==
308-
DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) {
309-
size_t length;
310-
dyldSharedCacheStart =
311-
(uintptr_t)_dyld_get_shared_cache_range(&length);
312-
dyldSharedCacheEnd =
313-
dyldSharedCacheStart ? dyldSharedCacheStart + length : 0;
314-
validateSharedCacheResults = runtime::environment::
315-
SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES();
316-
SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx",
317-
dyldSharedCacheStart, dyldSharedCacheEnd);
318-
} else {
319-
SHARED_CACHE_LOG(
320-
"Disabling shared cache optimizations due to unknown "
321-
"optimizations version %u",
322-
_dyld_swift_optimizations_version());
323-
dyldSharedCacheStart = 0;
324-
dyldSharedCacheEnd = 0;
306+
if (runtime::environment::SWIFT_DEBUG_ENABLE_SHARED_CACHE_PROTOCOL_CONFORMANCES()) {
307+
if (&_dyld_swift_optimizations_version) {
308+
if (_dyld_swift_optimizations_version() ==
309+
DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) {
310+
size_t length;
311+
dyldSharedCacheStart =
312+
(uintptr_t)_dyld_get_shared_cache_range(&length);
313+
dyldSharedCacheEnd =
314+
dyldSharedCacheStart ? dyldSharedCacheStart + length : 0;
315+
validateSharedCacheResults = runtime::environment::
316+
SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES();
317+
SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx",
318+
dyldSharedCacheStart, dyldSharedCacheEnd);
319+
} else {
320+
SHARED_CACHE_LOG(
321+
"Disabling shared cache optimizations due to unknown "
322+
"optimizations version %u",
323+
_dyld_swift_optimizations_version());
324+
dyldSharedCacheStart = 0;
325+
dyldSharedCacheEnd = 0;
326+
}
325327
}
326328
}
327329
}
@@ -608,8 +610,8 @@ static void validateSharedCacheResults(
608610
};
609611

610612
if (dyldCachedConformanceDescriptor) {
611-
if (!std::find(conformances.begin(), conformances.end(),
612-
dyldCachedConformanceDescriptor)) {
613+
if (std::find(conformances.begin(), conformances.end(),
614+
dyldCachedConformanceDescriptor) == conformances.end()) {
613615
auto typeName = swift_getTypeName(type, true);
614616
swift::fatalError(
615617
0,
@@ -775,7 +777,10 @@ swift_conformsToProtocolImpl(const Metadata *const type,
775777
}
776778

777779
if (dyldCachedConformanceDescriptor) {
778-
auto witness = dyldCachedConformanceDescriptor->getWitnessTable(type);
780+
ConformanceCandidate candidate(*dyldCachedConformanceDescriptor);
781+
auto *matchingType = candidate.getMatchingType(type);
782+
assert(matchingType);
783+
auto witness = dyldCachedConformanceDescriptor->getWitnessTable(matchingType);
779784
C.cacheResult(type, protocol, witness, /*always cache*/ 0);
780785
SHARED_CACHE_LOG("Caching generic conformance to %s found in shared cache",
781786
protocol->Name.get());

0 commit comments

Comments
 (0)