stdlib/public/runtime/ProtocolConformance.cpp
static
ConformanceCacheResult
searchInConformanceCache(const Metadata *type,
                         const ProtocolDescriptor *protocol) {
  auto &C = Conformances.get();
  auto origType = type;
  ConformanceCacheEntry *failureEntry = nullptr;

recur:
  {
    // Try the specific type first.
    if (auto *Value = C.findCached(type, protocol)) {
      if (Value->isSuccessful()) {
        // Found a conformance on the type or some superclass. Return it.
        return ConformanceCacheResult::cachedSuccess(Value->getWitnessTable());
      }

      // Found a negative cache entry.

      bool isAuthoritative;
      if (type == origType) {
        // This negative cache entry is for the original query type.
        // Remember it so it can be returned later.
        failureEntry = Value;
        // An up-to-date entry for the original type is authoritative.
        isAuthoritative = true;
      } else {
        // An up-to-date cached failure for a superclass of the type is not
        // authoritative: there may be a still-undiscovered conformance
        // for the original query type.
        isAuthoritative = false;
      }

      // Check if the negative cache entry is up-to-date.
      // FIXME: Using SectionsToScan.size() outside SectionsToScanLock
      // is undefined.
      if (Value->getFailureGeneration() == C.SectionsToScan.size()) {
        // Negative cache entry is up-to-date. Return failure along with
        // the original query type's own cache entry, if we found one.
        // (That entry may be out of date but the caller still has use for it.)
        return ConformanceCacheResult::cachedFailure(failureEntry,
                                                     isAuthoritative);
      }

      // Negative cache entry is out-of-date.
      // Continue searching for a better result.
    }
  }

  {
    // For generic and resilient types, nondependent conformances
    // are keyed by the nominal type descriptor rather than the
    // metadata, so try that.
    const auto *description = type->getNominalTypeDescriptor();

    // Hash and lookup the type-protocol pair in the cache.
    if (auto *Value = C.findCached(description, protocol)) {
      if (Value->isSuccessful())
        return ConformanceCacheResult::cachedSuccess(Value->getWitnessTable());

      // We don't try to cache negative responses for generic
      // patterns.
    }
  }

  // If the type is a class, try its superclass.
  if (const ClassMetadata *classType = type->getClassObject()) {
    if (classHasSuperclass(classType)) {
      type = getMetadataForClass(classType->SuperClass);
      goto recur;
    }
  }

  // We did not find an up-to-date cache entry.
  // If we found an out-of-date entry for the original query type then
  // return it (non-authoritatively). Otherwise return a cache miss.
  if (failureEntry)
    return ConformanceCacheResult::cachedFailure(failureEntry, false);
  else
    return ConformanceCacheResult::cacheMiss();
}
/// Search for a witness table in the ConformanceCache.
Search for a witness table in the ConformanceCache.
Search for a witness table in the ConformanceCache .
static
ConformanceCacheResult
searchInConformanceCache(const Metadata *type,
                         const ProtocolDescriptor *protocol) {
  auto &C = Conformances.get();
  auto origType = type;
  ConformanceCacheEntry *failureEntry = nullptr;
recur:
  {
    if (auto *Value = C.findCached(type, protocol)) {
      if (Value->isSuccessful()) {
        return ConformanceCacheResult::cachedSuccess(Value->getWitnessTable());
      }
      bool isAuthoritative;
      if (type == origType) {
        failureEntry = Value;
        isAuthoritative = true;
      } else {
        isAuthoritative = false;
      }
      if (Value->getFailureGeneration() == C.SectionsToScan.size()) {
        return ConformanceCacheResult::cachedFailure(failureEntry,
                                                     isAuthoritative);
      }
    }
  }
  {
    const auto *description = type->getNominalTypeDescriptor();
    if (auto *Value = C.findCached(description, protocol)) {
      if (Value->isSuccessful())
        return ConformanceCacheResult::cachedSuccess(Value->getWitnessTable());
    }
  }
  if (const ClassMetadata *classType = type->getClassObject()) {
    if (classHasSuperclass(classType)) {
      type = getMetadataForClass(classType->SuperClass);
      goto recur;
    }
  }
  if (failureEntry)
    return ConformanceCacheResult::cachedFailure(failureEntry, false);
  else
    return ConformanceCacheResult::cacheMiss();
}
static ConformanceCacheResult searchInConformanceCache ( const Metadata * type , const ProtocolDescriptor * protocol ) { auto & C = Conformances . get ( ) ; auto origType = type ; ConformanceCacheEntry * failureEntry = nullptr ; recur : { if ( auto * Value = C . findCached ( type , protocol ) ) { if ( Value -> isSuccessful ( ) ) { return ConformanceCacheResult :: cachedSuccess ( Value -> getWitnessTable ( ) ) ; } bool isAuthoritative ; if ( type == origType ) { failureEntry = Value ; isAuthoritative = true ; } else { isAuthoritative = false ; } if ( Value -> getFailureGeneration ( ) == C . SectionsToScan . size ( ) ) { return ConformanceCacheResult :: cachedFailure ( failureEntry , isAuthoritative ) ; } } } { const auto * description = type -> getNominalTypeDescriptor ( ) ; if ( auto * Value = C . findCached ( description , protocol ) ) { if ( Value -> isSuccessful ( ) ) return ConformanceCacheResult :: cachedSuccess ( Value -> getWitnessTable ( ) ) ; } } if ( const ClassMetadata * classType = type -> getClassObject ( ) ) { if ( classHasSuperclass ( classType ) ) { type = getMetadataForClass ( classType -> SuperClass ) ; goto recur ; } } if ( failureEntry ) return ConformanceCacheResult :: cachedFailure ( failureEntry , false ) ; else return ConformanceCacheResult :: cacheMiss ( ) ; }
Search for a witness table in the ConformanceCache.
Search for a witness table in the ConformanceCache .
// Try the specific type first. // Found a conformance on the type or some superclass. Return it. // Found a negative cache entry. // This negative cache entry is for the original query type. // Remember it so it can be returned later. // An up-to-date entry for the original type is authoritative. // An up-to-date cached failure for a superclass of the type is not // authoritative: there may be a still-undiscovered conformance // for the original query type. // Check if the negative cache entry is up-to-date. // FIXME: Using SectionsToScan.size() outside SectionsToScanLock // is undefined. // Negative cache entry is up-to-date. Return failure along with // the original query type's own cache entry, if we found one. // (That entry may be out of date but the caller still has use for it.) // Negative cache entry is out-of-date. // Continue searching for a better result. // For generic and resilient types, nondependent conformances // are keyed by the nominal type descriptor rather than the // metadata, so try that. // Hash and lookup the type-protocol pair in the cache. // We don't try to cache negative responses for generic // patterns. // If the type is a class, try its superclass. // We did not find an up-to-date cache entry. // If we found an out-of-date entry for the original query type then // return it (non-authoritatively). Otherwise return a cache miss.