@@ -650,42 +650,19 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
650
650
}
651
651
}
652
652
653
- // / Look for an property bag corresponding to the given key, returning nullptr
654
- // / if one has not been recorded.
655
- PropertyBag *
656
- PropertyMap::getPropertiesIfPresent (const MutableTerm &key) const {
657
- assert (!key.empty ());
658
-
659
- for (const auto &props : Map) {
660
- int compare = props->getKey ().compare (key, Protos);
661
- if (compare == 0 )
662
- return props.get ();
663
- if (compare > 0 )
664
- return nullptr ;
665
- }
666
-
667
- return nullptr ;
653
+ PropertyMap::~PropertyMap () {
654
+ Trie.updateHistograms (Context.PropertyTrieHistogram ,
655
+ Context.PropertyTrieRootHistogram );
656
+ clear ();
668
657
}
669
658
670
659
// / Look for an property bag corresponding to a suffix of the given key.
671
660
// /
672
661
// / Returns nullptr if no information is known about this key.
673
662
PropertyBag *
674
663
PropertyMap::lookUpProperties (const MutableTerm &key) const {
675
- if (auto *props = getPropertiesIfPresent (key))
676
- return props;
677
-
678
- auto begin = key.begin () + 1 ;
679
- auto end = key.end ();
680
-
681
- while (begin != end) {
682
- MutableTerm suffix (begin, end);
683
-
684
- if (auto *suffixClass = getPropertiesIfPresent (suffix))
685
- return suffixClass;
686
-
687
- ++begin;
688
- }
664
+ if (auto result = Trie.find (key.rbegin (), key.rend ()))
665
+ return *result;
689
666
690
667
return nullptr ;
691
668
}
@@ -695,17 +672,10 @@ PropertyMap::lookUpProperties(const MutableTerm &key) const {
695
672
// /
696
673
// / This must be called in monotonically non-decreasing key order.
697
674
PropertyBag *
698
- PropertyMap::getOrCreateProperties (const MutableTerm &key) {
699
- assert (!key.empty ());
700
-
701
- if (!Map.empty ()) {
702
- const auto &lastEquivClass = Map.back ();
703
- int compare = lastEquivClass->getKey ().compare (key, Protos);
704
- if (compare == 0 )
705
- return lastEquivClass.get ();
706
-
707
- assert (compare < 0 && " Must record property bags in sorted order" );
708
- }
675
+ PropertyMap::getOrCreateProperties (Term key) {
676
+ auto next = Trie.find (key.rbegin (), key.rend ());
677
+ if (next && (*next)->getKey () == key)
678
+ return *next;
709
679
710
680
auto *props = new PropertyBag (key);
711
681
@@ -730,23 +700,38 @@ PropertyMap::getOrCreateProperties(const MutableTerm &key) {
730
700
//
731
701
// Since 'A' has no proper suffix with additional properties, the next
732
702
// property bag of 'A' is nullptr.
733
- if (auto *next = lookUpProperties (key))
734
- props->copyPropertiesFrom (next, Context);
735
-
736
- Map.emplace_back (props);
703
+ if (next)
704
+ props->copyPropertiesFrom (*next, Context);
705
+
706
+ Entries.push_back (props);
707
+ auto oldProps = Trie.insert (key.rbegin (), key.rend (), props);
708
+ if (oldProps) {
709
+ llvm::errs () << " Duplicate property map entry for " << key << " \n " ;
710
+ llvm::errs () << " Old:\n " ;
711
+ (*oldProps)->dump (llvm::errs ());
712
+ llvm::errs () << " \n " ;
713
+ llvm::errs () << " New:\n " ;
714
+ props->dump (llvm::errs ());
715
+ llvm::errs () << " \n " ;
716
+ abort ();
717
+ }
737
718
738
719
return props;
739
720
}
740
721
741
722
void PropertyMap::clear () {
742
- Map.clear ();
723
+ for (auto *props : Entries)
724
+ delete props;
725
+
726
+ Trie.clear ();
727
+ Entries.clear ();
743
728
ConcreteTypeInDomainMap.clear ();
744
729
}
745
730
746
731
// / Record a protocol conformance, layout or superclass constraint on the given
747
732
// / key. Must be called in monotonically non-decreasing key order.
748
733
void PropertyMap::addProperty (
749
- const MutableTerm & key, Symbol property,
734
+ Term key, Symbol property,
750
735
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) {
751
736
assert (property.isProperty ());
752
737
auto *props = getOrCreateProperties (key);
@@ -757,7 +742,7 @@ void PropertyMap::addProperty(
757
742
// / For each fully-concrete type, find the shortest term having that concrete type.
758
743
// / This is later used by computeConstraintTermForTypeWitness().
759
744
void PropertyMap::computeConcreteTypeInDomainMap () {
760
- for (const auto &props : Map ) {
745
+ for (const auto &props : Entries ) {
761
746
if (!props->isConcreteType ())
762
747
continue ;
763
748
@@ -771,12 +756,8 @@ void PropertyMap::computeConcreteTypeInDomainMap() {
771
756
auto concreteTypeKey = std::make_pair (concreteType, domain);
772
757
773
758
auto found = ConcreteTypeInDomainMap.find (concreteTypeKey);
774
- if (found != ConcreteTypeInDomainMap.end ()) {
775
- const auto &otherTerm = found->second ;
776
- assert (props->Key .compare (otherTerm, Protos) > 0 &&
777
- " Out-of-order keys?" );
759
+ if (found != ConcreteTypeInDomainMap.end ())
778
760
continue ;
779
- }
780
761
781
762
auto inserted = ConcreteTypeInDomainMap.insert (
782
763
std::make_pair (concreteTypeKey, props->Key ));
@@ -787,7 +768,7 @@ void PropertyMap::computeConcreteTypeInDomainMap() {
787
768
788
769
void PropertyMap::concretizeNestedTypesFromConcreteParents (
789
770
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) const {
790
- for (const auto &props : Map ) {
771
+ for (const auto &props : Entries ) {
791
772
if (props->getConformsTo ().empty ())
792
773
continue ;
793
774
@@ -865,7 +846,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
865
846
// / T.[P:B] => U.V
866
847
// /
867
848
void PropertyMap::concretizeNestedTypesFromConcreteParent (
868
- const MutableTerm & key, RequirementKind requirementKind,
849
+ Term key, RequirementKind requirementKind,
869
850
CanType concreteType, ArrayRef<Term> substitutions,
870
851
ArrayRef<const ProtocolDecl *> conformsTo,
871
852
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
@@ -928,7 +909,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
928
909
<< " of " << concreteType << " is " << typeWitness << " \n " ;
929
910
}
930
911
931
- MutableTerm subjectType = key;
912
+ MutableTerm subjectType ( key) ;
932
913
subjectType.add (Symbol::forAssociatedType (proto, assocType->getName (),
933
914
Context));
934
915
@@ -944,7 +925,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
944
925
}
945
926
946
927
// Add a rule T.[P:A] => T.
947
- constraintType = key;
928
+ constraintType = MutableTerm ( key) ;
948
929
} else {
949
930
constraintType = computeConstraintTermForTypeWitness (
950
931
key, concreteType, typeWitness, subjectType,
@@ -985,7 +966,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
985
966
// /
986
967
// / T.[P:A] => V
987
968
MutableTerm PropertyMap::computeConstraintTermForTypeWitness (
988
- const MutableTerm & key, CanType concreteType, CanType typeWitness,
969
+ Term key, CanType concreteType, CanType typeWitness,
989
970
const MutableTerm &subjectType, ArrayRef<Term> substitutions) const {
990
971
if (!typeWitness->hasTypeParameter ()) {
991
972
// Check if we have a shorter representative we can use.
@@ -994,12 +975,13 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
994
975
995
976
auto found = ConcreteTypeInDomainMap.find (concreteTypeKey);
996
977
if (found != ConcreteTypeInDomainMap.end ()) {
997
- if (found->second != subjectType) {
978
+ MutableTerm result (found->second );
979
+ if (result != subjectType) {
998
980
if (DebugConcretizeNestedTypes) {
999
981
llvm::dbgs () << " ^^ Type witness can re-use property bag of "
1000
982
<< found->second << " \n " ;
1001
983
}
1002
- return found-> second ;
984
+ return result ;
1003
985
}
1004
986
}
1005
987
}
@@ -1030,7 +1012,7 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
1030
1012
1031
1013
void PropertyMap::dump (llvm::raw_ostream &out) const {
1032
1014
out << " Property map: {\n " ;
1033
- for (const auto &props : Map ) {
1015
+ for (const auto &props : Entries ) {
1034
1016
out << " " ;
1035
1017
props->dump (out);
1036
1018
out << " \n " ;
@@ -1056,7 +1038,11 @@ RewriteSystem::buildPropertyMap(PropertyMap &map,
1056
1038
unsigned maxDepth) {
1057
1039
map.clear ();
1058
1040
1059
- std::vector<std::pair<MutableTerm, Symbol>> properties;
1041
+ // PropertyMap::addRule() requires that shorter rules are added
1042
+ // before longer rules, so that it can perform lookups on suffixes and call
1043
+ // PropertyBag::copyPropertiesFrom(). However, we don't have to perform a
1044
+ // full sort by term order here; a bucket sort by term length suffices.
1045
+ SmallVector<std::vector<std::pair<Term, Symbol>>, 4 > properties;
1060
1046
1061
1047
for (const auto &rule : Rules) {
1062
1048
if (rule.isDeleted ())
@@ -1076,31 +1062,19 @@ RewriteSystem::buildPropertyMap(PropertyMap &map,
1076
1062
if (!std::equal (rhs.begin (), rhs.end (), lhs.begin ()))
1077
1063
continue ;
1078
1064
1079
- MutableTerm key (rhs);
1080
-
1081
- #ifndef NDEBUG
1082
- assert (!simplify (key) &&
1083
- " Right hand side of a property rule should already be reduced" );
1084
- #endif
1085
-
1086
- properties.emplace_back (key, property);
1065
+ if (rhs.size () >= properties.size ())
1066
+ properties.resize (rhs.size () + 1 );
1067
+ properties[rhs.size ()].emplace_back (rhs, property);
1087
1068
}
1088
1069
1089
- // PropertyMap::addRule() requires that shorter rules are added
1090
- // before longer rules, so that it can perform lookups on suffixes and call
1091
- // PropertyBag::copyPropertiesFrom().
1092
- std::sort (properties.begin (), properties.end (),
1093
- [&](const std::pair<MutableTerm, Symbol> &lhs,
1094
- const std::pair<MutableTerm, Symbol> &rhs) -> bool {
1095
- return lhs.first .compare (rhs.first , Protos) < 0 ;
1096
- });
1097
-
1098
1070
// Merging multiple superclass or concrete type rules can induce new rules
1099
1071
// to unify concrete type constructor arguments.
1100
1072
SmallVector<std::pair<MutableTerm, MutableTerm>, 3 > inducedRules;
1101
1073
1102
- for (auto pair : properties) {
1103
- map.addProperty (pair.first , pair.second , inducedRules);
1074
+ for (const auto &bucket : properties) {
1075
+ for (auto pair : bucket) {
1076
+ map.addProperty (pair.first , pair.second , inducedRules);
1077
+ }
1104
1078
}
1105
1079
1106
1080
// We collect terms with fully concrete types so that we can re-use them
0 commit comments