@@ -4740,20 +4740,38 @@ areAllTransitiveMetadataComplete_cheap(const Metadata *type) {
47404740// / dependencies actually hold, and we can keep going.
47414741static MetadataDependency
47424742checkTransitiveCompleteness (const Metadata *initialType) {
4743- // TODO: it would nice to avoid allocating memory in common cases here.
4744- // In particular, we don't usually add *anything* to the worklist, and we
4745- // usually only add a handful of types to the map.
4746- std::vector<const Metadata *> worklist;
4747- std::unordered_set<const Metadata *> presumedCompleteTypes;
4743+ llvm::SmallVector<const Metadata *, 8 > worklist;
4744+
4745+ // An efficient hash-set implementation in the spirit of llvm's SmallPtrSet:
4746+ // The first 8 elements are stored in an inline-allocated array to avoid
4747+ // malloc calls in the common case. Lookup is still reasonable fast because
4748+ // there are max 8 elements in the array.
4749+ const int InlineCapacity = 8 ;
4750+ const Metadata *inlinedPresumedCompleteTypes[InlineCapacity];
4751+ int numInlinedTypes = 0 ;
4752+ std::unordered_set<const Metadata *> overflowPresumedCompleteTypes;
47484753
47494754 MetadataDependency dependency;
47504755 auto isIncomplete = [&](const Metadata *type) -> bool {
47514756 // Add the type to the presumed-complete-types set. If this doesn't
47524757 // succeed, we've already inserted it, which means we must have already
47534758 // decided it was complete.
4754- if (!presumedCompleteTypes.insert (type).second )
4759+ // First, try to find the type in the inline-storage of the set.
4760+ const Metadata **end = inlinedPresumedCompleteTypes + numInlinedTypes;
4761+ if (std::find (inlinedPresumedCompleteTypes, end, type) != end)
47554762 return false ;
47564763
4764+ // We didn't find the type in the inline-storage.
4765+ if (numInlinedTypes < InlineCapacity) {
4766+ assert (overflowPresumedCompleteTypes.size () == 0 );
4767+ inlinedPresumedCompleteTypes[numInlinedTypes++] = type;
4768+ } else {
4769+ // The inline-storage is full. So try to insert the type into the
4770+ // overflow set.
4771+ if (!overflowPresumedCompleteTypes.insert (type).second )
4772+ return false ;
4773+ }
4774+
47574775 // Check the metadata's current state with a non-blocking request.
47584776 auto request = MetadataRequest (MetadataState::Complete,
47594777 /* non-blocking*/ true );
@@ -4780,7 +4798,9 @@ checkTransitiveCompleteness(const Metadata *initialType) {
47804798
47814799 // Consider the type itself to be presumed-complete. We're looking for
47824800 // a greatest fixed point.
4783- presumedCompleteTypes.insert (initialType);
4801+ assert (numInlinedTypes == 0 && overflowPresumedCompleteTypes.size () == 0 );
4802+ inlinedPresumedCompleteTypes[0 ] = initialType;
4803+ numInlinedTypes = 1 ;
47844804 if (findAnyTransitiveMetadata (initialType, isIncomplete))
47854805 return dependency;
47864806
0 commit comments