From a9b573deef8be2894fe2802e997ea2a5c65af42b Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Fri, 17 Jun 2022 16:43:42 -0400 Subject: [PATCH] [5.7][Runtime] Fix short-circuiting of shared cache conformance lookups. We were skipping shared cache queries if the ObjC metadata or descriptor were outside the shared cache, but we need to skip only if they're both outside the shared cache. We also need to check foreign types even if the descriptor is outside the shared cache. rdar://93931813 (cherry picked from commit f2407bf0a70991bb52df0ddb94fed2f801a1de5a) --- stdlib/public/runtime/ProtocolConformance.cpp | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 861c1a0e5e9d9..5e33065ae54aa 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -802,20 +802,18 @@ static _dyld_protocol_conformance_result getDyldSharedCacheConformance( ConformanceState &C, const ProtocolDescriptor *protocol, const ClassMetadata *objcClassMetadata, const ContextDescriptor *description, llvm::StringRef foreignTypeIdentity) { - // Protocols, classes, and descriptions that aren't in the shared cache will - // never be found in the shared cache conformances. Foreign types are - // non-unique so those can still be found in the shared cache regardless of - // where the we got the identity. - if (!C.inSharedCache(protocol) || - (objcClassMetadata && !C.inSharedCache(objcClassMetadata)) || - (description && !C.inSharedCache(description))) { - DYLD_CONFORMANCES_LOG("Skipping shared cache lookup, protocol %p, class " - "%p, or description %p is not in shared cache.", - protocol, objcClassMetadata, description); + // Protocols that aren't in the shared cache will never be found in the shared + // cache conformances, skip the call. + if (!C.inSharedCache(protocol)) { + DYLD_CONFORMANCES_LOG( + "Skipping shared cache lookup, protocol %p is not in shared cache.", + protocol); return {_dyld_protocol_conformance_result_kind_not_found, nullptr}; } if (!foreignTypeIdentity.empty()) { + // Foreign types are non-unique so those can still be found in the shared + // cache even if the identity string is outside. DYLD_CONFORMANCES_LOG( "_dyld_find_foreign_type_protocol_conformance(%p, %.*s, %zu)", protocol, (int)foreignTypeIdentity.size(), foreignTypeIdentity.data(), @@ -823,6 +821,17 @@ static _dyld_protocol_conformance_result getDyldSharedCacheConformance( return _dyld_find_foreign_type_protocol_conformance( protocol, foreignTypeIdentity.data(), foreignTypeIdentity.size()); } else { + // If both the ObjC class metadata and description are outside the shared + // cache, then we'll never find a shared cache conformance, skip the call. + // We can still find a shared cache conformance if one is inside and one is + // outside. + if (!C.inSharedCache(objcClassMetadata) && !C.inSharedCache(description)) { + DYLD_CONFORMANCES_LOG("Skipping shared cache lookup, class %p and " + "description %p are not in shared cache.", + objcClassMetadata, description); + return {_dyld_protocol_conformance_result_kind_not_found, nullptr}; + } + DYLD_CONFORMANCES_LOG("_dyld_find_protocol_conformance(%p, %p, %p)", protocol, objcClassMetadata, description); return _dyld_find_protocol_conformance(protocol, objcClassMetadata, @@ -876,9 +885,11 @@ findConformanceWithDyld(ConformanceState &C, const Metadata *type, auto objcClassMetadata = swift_getObjCClassFromMetadataConditional(type); #if SHARED_CACHE_LOG_ENABLED auto typeName = swift_getTypeName(type, true); - DYLD_CONFORMANCES_LOG("Looking up conformance of %.*s to %s", - (int)typeName.length, typeName.data, - protocol->Name.get()); + DYLD_CONFORMANCES_LOG("Looking up conformance of %.*s (type=%p, " + "objcClassMetadata=%p, description=%p) to %s (%p)", + (int)typeName.length, typeName.data, type, + objcClassMetadata, description, protocol->Name.get(), + protocol); #endif _dyld_protocol_conformance_result dyldResult; if (C.scanSectionsBackwards) {