[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,22 +302,28 @@ struct ConformanceState {
runtime::bincompat::workaroundProtocolConformanceReverseIteration(); runtime::bincompat::workaroundProtocolConformanceReverseIteration();
#if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES #if USE_DYLD_SHARED_CACHE_CONFORMANCE_TABLES
if (_dyld_swift_optimizations_version() == if (__builtin_available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)) {
DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) { if (&_dyld_swift_optimizations_version) {
size_t length; if (_dyld_swift_optimizations_version() ==
dyldSharedCacheStart = (uintptr_t)_dyld_get_shared_cache_range(&length); DYLD_EXPECTED_SWIFT_OPTIMIZATIONS_VERSION) {
dyldSharedCacheEnd = size_t length;
dyldSharedCacheStart ? dyldSharedCacheStart + length : 0; dyldSharedCacheStart =
validateSharedCacheResults = runtime::environment:: (uintptr_t)_dyld_get_shared_cache_range(&length);
SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES(); dyldSharedCacheEnd =
SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx", dyldSharedCacheStart, dyldSharedCacheStart ? dyldSharedCacheStart + length : 0;
dyldSharedCacheEnd); validateSharedCacheResults = runtime::environment::
} else { SWIFT_DEBUG_VALIDATE_SHARED_CACHE_PROTOCOL_CONFORMANCES();
SHARED_CACHE_LOG("Disabling shared cache optimizations due to unknown " SHARED_CACHE_LOG("Shared cache range is %#lx-%#lx",
"optimizations version %u", dyldSharedCacheStart, dyldSharedCacheEnd);
_dyld_swift_optimizations_version()); } else {
dyldSharedCacheStart = 0; SHARED_CACHE_LOG(
dyldSharedCacheEnd = 0; "Disabling shared cache optimizations due to unknown "
"optimizations version %u",
_dyld_swift_optimizations_version());
dyldSharedCacheStart = 0;
dyldSharedCacheEnd = 0;
}
}
} }
#endif #endif
@@ -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,29 +736,30 @@ 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).
const Metadata *dyldSearchType = type; if (C.sharedCacheOptimizationsActive()) {
do { const Metadata *dyldSearchType = type;
bool definitiveFailure; do {
std::tie(dyldCachedWitnessTable, dyldCachedConformanceDescriptor, bool definitiveFailure;
definitiveFailure) = std::tie(dyldCachedWitnessTable, dyldCachedConformanceDescriptor,
findSharedCacheConformance(C, dyldSearchType, protocol); definitiveFailure) =
findSharedCacheConformance(C, dyldSearchType, protocol);
if (definitiveFailure) if (definitiveFailure)
return nullptr; return nullptr;
dyldSearchType = _swift_class_getSuperclass(dyldSearchType); dyldSearchType = _swift_class_getSuperclass(dyldSearchType);
} while (dyldSearchType && !dyldCachedWitnessTable && } while (dyldSearchType && !dyldCachedWitnessTable &&
!dyldCachedConformanceDescriptor); !dyldCachedConformanceDescriptor);
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