Skip to content

Commit b55ec9b

Browse files
committed
slab allocate template candidates
1 parent 183fd33 commit b55ec9b

File tree

2 files changed

+130
-75
lines changed

2 files changed

+130
-75
lines changed

clang/include/clang/Sema/Overload.h

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
#include <cstddef>
3939
#include <cstdint>
4040
#include <utility>
41-
#include <variant>
4241

4342
namespace clang {
4443

@@ -1039,60 +1038,61 @@ class Sema;
10391038
RewriteKind(CRK_None) {}
10401039
};
10411040

1042-
struct DeferredConversionTemplateOverloadCandidate {
1043-
FunctionTemplateDecl *FunctionTemplate;
1044-
DeclAccessPair FoundDecl;
1045-
CXXRecordDecl *ActingContext;
1046-
Expr *From;
1047-
QualType ToType;
1041+
struct DeferredTemplateOverloadCandidate {
1042+
DeferredTemplateOverloadCandidate *Next = nullptr;
1043+
enum Kind { Function, Method, Conversion };
10481044

1045+
LLVM_PREFERRED_TYPE(Kind)
1046+
unsigned Kind : 2;
10491047
LLVM_PREFERRED_TYPE(bool)
10501048
unsigned AllowObjCConversionOnExplicit : 1;
10511049
LLVM_PREFERRED_TYPE(bool)
1050+
unsigned AllowResultConversion : 1;
1051+
LLVM_PREFERRED_TYPE(bool)
10521052
unsigned AllowExplicit : 1;
10531053
LLVM_PREFERRED_TYPE(bool)
1054-
unsigned AllowResultConversion : 1;
1054+
unsigned SuppressUserConversions : 1;
1055+
LLVM_PREFERRED_TYPE(bool)
1056+
unsigned PartialOverloading : 1;
1057+
LLVM_PREFERRED_TYPE(bool)
1058+
unsigned AggregateCandidateDeduction : 1;
10551059
};
10561060

1057-
struct DeferredMethodTemplateOverloadCandidate {
1061+
struct DeferredFunctionTemplateOverloadCandidate
1062+
: public DeferredTemplateOverloadCandidate {
10581063
FunctionTemplateDecl *FunctionTemplate;
10591064
DeclAccessPair FoundDecl;
10601065
ArrayRef<Expr *> Args;
1061-
CXXRecordDecl *ActingContext;
1062-
Expr::Classification ObjectClassification;
1063-
QualType ObjectType;
1064-
1066+
CallExpr::ADLCallKind IsADLCandidate;
10651067
OverloadCandidateParamOrder PO;
1066-
LLVM_PREFERRED_TYPE(bool)
1067-
unsigned SuppressUserConversions : 1;
1068-
LLVM_PREFERRED_TYPE(bool)
1069-
unsigned PartialOverloading : 1;
10701068
};
1069+
static_assert(std::is_trivially_destructible_v<
1070+
DeferredFunctionTemplateOverloadCandidate>);
10711071

1072-
struct DeferredFunctionTemplateOverloadCandidate {
1072+
struct DeferredMethodTemplateOverloadCandidate
1073+
: public DeferredTemplateOverloadCandidate {
10731074
FunctionTemplateDecl *FunctionTemplate;
10741075
DeclAccessPair FoundDecl;
10751076
ArrayRef<Expr *> Args;
1076-
1077-
CallExpr::ADLCallKind IsADLCandidate;
1077+
CXXRecordDecl *ActingContext;
1078+
Expr::Classification ObjectClassification;
1079+
QualType ObjectType;
10781080
OverloadCandidateParamOrder PO;
1079-
LLVM_PREFERRED_TYPE(bool)
1080-
unsigned SuppressUserConversions : 1;
1081-
LLVM_PREFERRED_TYPE(bool)
1082-
unsigned PartialOverloading : 1;
1083-
LLVM_PREFERRED_TYPE(bool)
1084-
unsigned AllowExplicit : 1;
1085-
LLVM_PREFERRED_TYPE(bool)
1086-
unsigned AggregateCandidateDeduction : 1;
10871081
};
1082+
static_assert(std::is_trivially_destructible_v<
1083+
DeferredMethodTemplateOverloadCandidate>);
10881084

1089-
using DeferredTemplateOverloadCandidate =
1090-
std::variant<DeferredConversionTemplateOverloadCandidate,
1091-
DeferredMethodTemplateOverloadCandidate,
1092-
DeferredFunctionTemplateOverloadCandidate>;
1085+
struct DeferredConversionTemplateOverloadCandidate
1086+
: public DeferredTemplateOverloadCandidate {
1087+
FunctionTemplateDecl *FunctionTemplate;
1088+
DeclAccessPair FoundDecl;
1089+
CXXRecordDecl *ActingContext;
1090+
Expr *From;
1091+
QualType ToType;
1092+
};
10931093

1094-
static_assert(
1095-
std::is_trivially_destructible_v<DeferredTemplateOverloadCandidate>);
1094+
static_assert(std::is_trivially_destructible_v<
1095+
DeferredConversionTemplateOverloadCandidate>);
10961096

10971097
/// OverloadCandidateSet - A set of overload candidates, used in C++
10981098
/// overload resolution (C++ 13.3).
@@ -1197,8 +1197,9 @@ class Sema;
11971197
private:
11981198
SmallVector<OverloadCandidate, 16> Candidates;
11991199
llvm::SmallPtrSet<uintptr_t, 16> Functions;
1200-
SmallVector<DeferredTemplateOverloadCandidate, 8> DeferredCandidates;
12011200

1201+
DeferredTemplateOverloadCandidate *FirstDeferredCandidate;
1202+
unsigned DeferredCandidatesCount : 8 * sizeof(unsigned) - 1;
12021203
LLVM_PREFERRED_TYPE(bool)
12031204
unsigned HasDeferredTemplateConstructors : 1;
12041205

@@ -1246,12 +1247,27 @@ class Sema;
12461247
return reinterpret_cast<T *>(FreeSpaceStart);
12471248
}
12481249

1250+
template <typename T> T *allocateDeferredCandidate() {
1251+
T *C = slabAllocate<T>(1);
1252+
if (!FirstDeferredCandidate)
1253+
FirstDeferredCandidate = C;
1254+
else {
1255+
auto *F = FirstDeferredCandidate;
1256+
while (F->Next)
1257+
F = F->Next;
1258+
F->Next = C;
1259+
}
1260+
DeferredCandidatesCount++;
1261+
return C;
1262+
}
1263+
12491264
void destroyCandidates();
12501265

12511266
public:
12521267
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
12531268
OperatorRewriteInfo RewriteInfo = {})
1254-
: HasDeferredTemplateConstructors(false), Loc(Loc), Kind(CSK),
1269+
: FirstDeferredCandidate(nullptr), DeferredCandidatesCount(0),
1270+
HasDeferredTemplateConstructors(false), Loc(Loc), Kind(CSK),
12551271
RewriteInfo(RewriteInfo) {}
12561272
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
12571273
OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
@@ -1290,11 +1306,9 @@ class Sema;
12901306
iterator begin() { return Candidates.begin(); }
12911307
iterator end() { return Candidates.end(); }
12921308

1293-
size_t size() const {
1294-
return Candidates.size() + DeferredCandidates.size();
1295-
}
1309+
size_t size() const { return Candidates.size() + DeferredCandidatesCount; }
12961310
bool empty() const {
1297-
return Candidates.empty() && DeferredCandidates.empty();
1311+
return Candidates.empty() && DeferredCandidatesCount == 0;
12981312
}
12991313

13001314
/// Allocate storage for conversion sequences for NumConversions

clang/lib/Sema/SemaOverload.cpp

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,8 @@ void OverloadCandidateSet::clear(CandidateSetKind CSK) {
11241124
Candidates.clear();
11251125
Functions.clear();
11261126
Kind = CSK;
1127+
FirstDeferredCandidate = nullptr;
1128+
DeferredCandidatesCount = 0;
11271129
HasDeferredTemplateConstructors = false;
11281130
}
11291131

@@ -11012,16 +11014,20 @@ void OverloadCandidateSet::AddDeferredTemplateCandidate(
1101211014
bool PartialOverloading, bool AllowExplicit,
1101311015
CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
1101411016
bool AggregateCandidateDeduction) {
11015-
DeferredFunctionTemplateOverloadCandidate C{FunctionTemplate,
11016-
FoundDecl,
11017-
Args,
11018-
IsADLCandidate,
11019-
PO,
11020-
SuppressUserConversions,
11021-
PartialOverloading,
11022-
AllowExplicit,
11023-
AggregateCandidateDeduction};
11024-
DeferredCandidates.emplace_back(std::move(C));
11017+
11018+
auto *C =
11019+
allocateDeferredCandidate<DeferredFunctionTemplateOverloadCandidate>();
11020+
11021+
C = new (C) DeferredFunctionTemplateOverloadCandidate{
11022+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Function,
11023+
/*AllowObjCConversionOnExplicit=*/false,
11024+
/*AllowResultConversion=*/false, AllowExplicit, SuppressUserConversions,
11025+
PartialOverloading, AggregateCandidateDeduction},
11026+
FunctionTemplate,
11027+
FoundDecl,
11028+
Args,
11029+
IsADLCandidate,
11030+
PO};
1102511031
HasDeferredTemplateConstructors |=
1102611032
isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl());
1102711033
}
@@ -11032,11 +11038,23 @@ void OverloadCandidateSet::AddDeferredMethodTemplateCandidate(
1103211038
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
1103311039
bool SuppressUserConversions, bool PartialOverloading,
1103411040
OverloadCandidateParamOrder PO) {
11035-
DeferredMethodTemplateOverloadCandidate C{
11036-
MethodTmpl, FoundDecl, Args, ActingContext,
11037-
ObjectClassification, ObjectType, PO, SuppressUserConversions,
11038-
PartialOverloading};
11039-
DeferredCandidates.emplace_back(std::move(C));
11041+
11042+
auto *C =
11043+
allocateDeferredCandidate<DeferredMethodTemplateOverloadCandidate>();
11044+
11045+
C = new (C) DeferredMethodTemplateOverloadCandidate{
11046+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Method,
11047+
/*AllowObjCConversionOnExplicit=*/false,
11048+
/*AllowResultConversion=*/false,
11049+
/*AllowExplicit=*/false, SuppressUserConversions, PartialOverloading,
11050+
/*AggregateCandidateDeduction=*/false},
11051+
MethodTmpl,
11052+
FoundDecl,
11053+
Args,
11054+
ActingContext,
11055+
ObjectClassification,
11056+
ObjectType,
11057+
PO};
1104011058
}
1104111059

1104211060
void OverloadCandidateSet::AddDeferredConversionTemplateCandidate(
@@ -11045,18 +11063,26 @@ void OverloadCandidateSet::AddDeferredConversionTemplateCandidate(
1104511063
bool AllowObjCConversionOnExplicit, bool AllowExplicit,
1104611064
bool AllowResultConversion) {
1104711065

11048-
DeferredConversionTemplateOverloadCandidate C{
11049-
FunctionTemplate, FoundDecl,
11050-
ActingContext, From,
11051-
ToType, AllowObjCConversionOnExplicit,
11052-
AllowExplicit, AllowResultConversion};
11066+
auto *C =
11067+
allocateDeferredCandidate<DeferredConversionTemplateOverloadCandidate>();
1105311068

11054-
DeferredCandidates.emplace_back(std::move(C));
11069+
C = new (C) DeferredConversionTemplateOverloadCandidate{
11070+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Conversion,
11071+
AllowObjCConversionOnExplicit, AllowResultConversion,
11072+
/*AllowExplicit=*/false,
11073+
/*SuppressUserConversions=*/false,
11074+
/*PartialOverloading*/ false,
11075+
/*AggregateCandidateDeduction=*/false},
11076+
FunctionTemplate,
11077+
FoundDecl,
11078+
ActingContext,
11079+
From,
11080+
ToType};
1105511081
}
1105611082

1105711083
static void
1105811084
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11059-
DeferredMethodTemplateOverloadCandidate &&C) {
11085+
DeferredMethodTemplateOverloadCandidate &C) {
1106011086

1106111087
AddMethodTemplateCandidateImmediately(
1106211088
S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext,
@@ -11066,7 +11092,7 @@ AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
1106611092

1106711093
static void
1106811094
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11069-
DeferredFunctionTemplateOverloadCandidate &&C) {
11095+
DeferredFunctionTemplateOverloadCandidate &C) {
1107011096
AddTemplateOverloadCandidateImmediately(
1107111097
S, CandidateSet, C.FunctionTemplate, C.FoundDecl,
1107211098
/*ExplicitTemplateArgs=*/nullptr, C.Args, C.SuppressUserConversions,
@@ -11076,23 +11102,38 @@ AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
1107611102

1107711103
static void
1107811104
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11079-
DeferredConversionTemplateOverloadCandidate &&C) {
11105+
DeferredConversionTemplateOverloadCandidate &C) {
1108011106
return AddTemplateConversionCandidateImmediately(
1108111107
S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, C.From,
1108211108
C.ToType, C.AllowObjCConversionOnExplicit, C.AllowExplicit,
1108311109
C.AllowResultConversion);
1108411110
}
1108511111

1108611112
void OverloadCandidateSet::InjectNonDeducedTemplateCandidates(Sema &S) {
11087-
Candidates.reserve(Candidates.size() + DeferredCandidates.size());
11088-
for (auto &&Elem : DeferredCandidates) {
11089-
std::visit(
11090-
[&](auto &&Cand) {
11091-
AddTemplateOverloadCandidate(S, *this, std::move(Cand));
11092-
},
11093-
Elem);
11113+
Candidates.reserve(Candidates.size() + DeferredCandidatesCount);
11114+
DeferredTemplateOverloadCandidate *Cand = FirstDeferredCandidate;
11115+
while (Cand) {
11116+
switch (Cand->Kind) {
11117+
case DeferredTemplateOverloadCandidate::Function:
11118+
AddTemplateOverloadCandidate(
11119+
S, *this,
11120+
*static_cast<DeferredFunctionTemplateOverloadCandidate *>(Cand));
11121+
break;
11122+
case DeferredTemplateOverloadCandidate::Method:
11123+
AddTemplateOverloadCandidate(
11124+
S, *this,
11125+
*static_cast<DeferredMethodTemplateOverloadCandidate *>(Cand));
11126+
break;
11127+
case DeferredTemplateOverloadCandidate::Conversion:
11128+
AddTemplateOverloadCandidate(
11129+
S, *this,
11130+
*static_cast<DeferredConversionTemplateOverloadCandidate *>(Cand));
11131+
break;
11132+
}
11133+
Cand = Cand->Next;
1109411134
}
11095-
DeferredCandidates.clear();
11135+
FirstDeferredCandidate = nullptr;
11136+
DeferredCandidatesCount = 0;
1109611137
}
1109711138

1109811139
OverloadingResult
@@ -11155,10 +11196,10 @@ OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S,
1115511196
iterator &Best) {
1115611197

1115711198
assert(shouldDeferTemplateArgumentDeduction(S.getLangOpts()) ||
11158-
DeferredCandidates.empty() &&
11199+
DeferredCandidatesCount == 0 &&
1115911200
"Unexpected deferred template candidate");
1116011201

11161-
bool TwoPhaseResolution = !DeferredCandidates.empty();
11202+
bool TwoPhaseResolution = DeferredCandidatesCount != 0;
1116211203

1116311204
if (TwoPhaseResolution) {
1116411205

@@ -11269,7 +11310,7 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl(
1126911310

1127011311
OverloadingResult R = ResultForBestCandidate(Best);
1127111312

11272-
if (DeferredCandidates.empty() && !EquivalentCands.empty())
11313+
if (!EquivalentCands.empty())
1127311314
S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
1127411315
EquivalentCands);
1127511316
return R;

0 commit comments

Comments
 (0)