[Runtime] NULL/availability check shared cache calls.

Avoid a dynamic linker failure if the calls aren't available at runtime.

rdar://74965969
This commit is contained in:
Mike Ash
2021-03-03 15:31:45 -05:00
parent 109a33cf2b
commit e06c978cf8

View File

@@ -291,6 +291,10 @@ struct ConformanceState {
auto uintPtr = reinterpret_cast<uintptr_t>(ptr); auto uintPtr = reinterpret_cast<uintptr_t>(ptr);
return dyldSharedCacheStart <= uintPtr && uintPtr < dyldSharedCacheEnd; return dyldSharedCacheStart <= uintPtr && uintPtr < dyldSharedCacheEnd;
} }
bool sharedCacheOptimizationsActive() { return dyldSharedCacheStart != 0; }
#else
bool sharedCacheOptimizationsActive() { return false; }
#endif #endif
ConformanceState() { ConformanceState() {
@@ -298,23 +302,29 @@ struct ConformanceState {
runtime::bincompat::workaroundProtocolConformanceReverseIteration(); runtime::bincompat::workaroundProtocolConformanceReverseIteration();
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES #if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
if (__builtin_available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)) {
if (&_dyld_swift_optimizations_version) {
if (_dyld_swift_optimizations_version() == if (_dyld_swift_optimizations_version() ==
DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) { DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) {
size_t length; size_t length;
dyldSharedCacheStart = (uintptr_t)_dyld_get_shared_cache_range(&length); dyldSharedCacheStart =
(uintptr_t)_dyld_get_shared_cache_range(&length);
dyldSharedCacheEnd = dyldSharedCacheEnd =
dyldSharedCacheStart ? dyldSharedCacheStart + length : 0; dyldSharedCacheStart ? dyldSharedCacheStart + length : 0;
validateSharedCacheResults = runtime::environment:: validateSharedCacheResults = runtime::environment::
SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES(); SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES();
SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx", dyldSharedCacheStart, SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx",
dyldSharedCacheEnd); dyldSharedCacheStart, dyldSharedCacheEnd);
} else { } else {
SHARED_CACHE_LOG("Disabling shared cache optimizations due to unknown " SHARED_CACHE_LOG(
"Disabling shared cache optimizations due to unknown "
"optimizations version %u", "optimizations version %u",
_dyld_swift_optimizations_version()); _dyld_swift_optimizations_version());
dyldSharedCacheStart = 0; dyldSharedCacheStart = 0;
dyldSharedCacheEnd = 0; dyldSharedCacheEnd = 0;
} }
}
}
#endif #endif
// This must run last, as it triggers callbacks that require // This must run last, as it triggers callbacks that require
@@ -570,7 +580,7 @@ static void validateSharedCacheResults(
const WitnessTable *dyldCachedWitnessTable, const WitnessTable *dyldCachedWitnessTable,
const ProtocolConformanceDescriptor *dyldCachedConformanceDescriptor) { const ProtocolConformanceDescriptor *dyldCachedConformanceDescriptor) {
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES #if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
if (!C.validateSharedCacheResults) if (!C.sharedCacheOptimizationsActive() || !C.validateSharedCacheResults)
return; return;
llvm::SmallVector<const ProtocolConformanceDescriptor *, 8> conformances; llvm::SmallVector<const ProtocolConformanceDescriptor *, 8> conformances;
@@ -726,6 +736,7 @@ swift_conformsToProtocolImpl(const Metadata *const type,
// Search the shared cache tables for a conformance for this type, and for // Search the shared cache tables for a conformance for this type, and for
// superclasses (if it's a class). // superclasses (if it's a class).
if (C.sharedCacheOptimizationsActive()) {
const Metadata *dyldSearchType = type; const Metadata *dyldSearchType = type;
do { do {
bool definitiveFailure; bool definitiveFailure;
@@ -742,13 +753,13 @@ swift_conformsToProtocolImpl(const Metadata *const type,
validateSharedCacheResults(C, type, protocol, dyldCachedWitnessTable, validateSharedCacheResults(C, type, protocol, dyldCachedWitnessTable,
dyldCachedConformanceDescriptor); dyldCachedConformanceDescriptor);
// Return a cached result if we got a witness table. We can't do this if // Return a cached result if we got a witness table. We can't do this if
// scanSectionsBackwards is set, since a scanned conformance can override a // scanSectionsBackwards is set, since a scanned conformance can override a
// cached result in that case. // cached result in that case.
if (!C.scanSectionsBackwards) if (!C.scanSectionsBackwards)
if (dyldCachedWitnessTable) if (dyldCachedWitnessTable)
return dyldCachedWitnessTable; return dyldCachedWitnessTable;
}
// See if we have an authoritative cached conformance. The // See if we have an authoritative cached conformance. The
// ConcurrentReadableHashMap data structure allows us to search the map // ConcurrentReadableHashMap data structure allows us to search the map