@@ -4740,20 +4740,38 @@ areAllTransitiveMetadataComplete_cheap(const Metadata *type) {
4740
4740
// / dependencies actually hold, and we can keep going.
4741
4741
static MetadataDependency
4742
4742
checkTransitiveCompleteness (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;
4748
4753
4749
4754
MetadataDependency dependency;
4750
4755
auto isIncomplete = [&](const Metadata *type) -> bool {
4751
4756
// Add the type to the presumed-complete-types set. If this doesn't
4752
4757
// succeed, we've already inserted it, which means we must have already
4753
4758
// 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)
4755
4762
return false ;
4756
4763
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
+
4757
4775
// Check the metadata's current state with a non-blocking request.
4758
4776
auto request = MetadataRequest (MetadataState::Complete,
4759
4777
/* non-blocking*/ true );
@@ -4780,7 +4798,9 @@ checkTransitiveCompleteness(const Metadata *initialType) {
4780
4798
4781
4799
// Consider the type itself to be presumed-complete. We're looking for
4782
4800
// a greatest fixed point.
4783
- presumedCompleteTypes.insert (initialType);
4801
+ assert (numInlinedTypes == 0 && overflowPresumedCompleteTypes.size () == 0 );
4802
+ inlinedPresumedCompleteTypes[0 ] = initialType;
4803
+ numInlinedTypes = 1 ;
4784
4804
if (findAnyTransitiveMetadata (initialType, isIncomplete))
4785
4805
return dependency;
4786
4806
0 commit comments