Skip to content

Commit da7fcd9

Browse files
committed
slab allocate template candidates
1 parent 3be7712 commit da7fcd9

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

@@ -11004,16 +11006,20 @@ void OverloadCandidateSet::AddDeferredTemplateCandidate(
1100411006
bool PartialOverloading, bool AllowExplicit,
1100511007
CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
1100611008
bool AggregateCandidateDeduction) {
11007-
DeferredFunctionTemplateOverloadCandidate C{FunctionTemplate,
11008-
FoundDecl,
11009-
Args,
11010-
IsADLCandidate,
11011-
PO,
11012-
SuppressUserConversions,
11013-
PartialOverloading,
11014-
AllowExplicit,
11015-
AggregateCandidateDeduction};
11016-
DeferredCandidates.emplace_back(std::move(C));
11009+
11010+
auto *C =
11011+
allocateDeferredCandidate<DeferredFunctionTemplateOverloadCandidate>();
11012+
11013+
C = new (C) DeferredFunctionTemplateOverloadCandidate{
11014+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Function,
11015+
/*AllowObjCConversionOnExplicit=*/false,
11016+
/*AllowResultConversion=*/false, AllowExplicit, SuppressUserConversions,
11017+
PartialOverloading, AggregateCandidateDeduction},
11018+
FunctionTemplate,
11019+
FoundDecl,
11020+
Args,
11021+
IsADLCandidate,
11022+
PO};
1101711023
HasDeferredTemplateConstructors |=
1101811024
isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl());
1101911025
}
@@ -11024,11 +11030,23 @@ void OverloadCandidateSet::AddDeferredMethodTemplateCandidate(
1102411030
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
1102511031
bool SuppressUserConversions, bool PartialOverloading,
1102611032
OverloadCandidateParamOrder PO) {
11027-
DeferredMethodTemplateOverloadCandidate C{
11028-
MethodTmpl, FoundDecl, Args, ActingContext,
11029-
ObjectClassification, ObjectType, PO, SuppressUserConversions,
11030-
PartialOverloading};
11031-
DeferredCandidates.emplace_back(std::move(C));
11033+
11034+
auto *C =
11035+
allocateDeferredCandidate<DeferredMethodTemplateOverloadCandidate>();
11036+
11037+
C = new (C) DeferredMethodTemplateOverloadCandidate{
11038+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Method,
11039+
/*AllowObjCConversionOnExplicit=*/false,
11040+
/*AllowResultConversion=*/false,
11041+
/*AllowExplicit=*/false, SuppressUserConversions, PartialOverloading,
11042+
/*AggregateCandidateDeduction=*/false},
11043+
MethodTmpl,
11044+
FoundDecl,
11045+
Args,
11046+
ActingContext,
11047+
ObjectClassification,
11048+
ObjectType,
11049+
PO};
1103211050
}
1103311051

1103411052
void OverloadCandidateSet::AddDeferredConversionTemplateCandidate(
@@ -11037,18 +11055,26 @@ void OverloadCandidateSet::AddDeferredConversionTemplateCandidate(
1103711055
bool AllowObjCConversionOnExplicit, bool AllowExplicit,
1103811056
bool AllowResultConversion) {
1103911057

11040-
DeferredConversionTemplateOverloadCandidate C{
11041-
FunctionTemplate, FoundDecl,
11042-
ActingContext, From,
11043-
ToType, AllowObjCConversionOnExplicit,
11044-
AllowExplicit, AllowResultConversion};
11058+
auto *C =
11059+
allocateDeferredCandidate<DeferredConversionTemplateOverloadCandidate>();
1104511060

11046-
DeferredCandidates.emplace_back(std::move(C));
11061+
C = new (C) DeferredConversionTemplateOverloadCandidate{
11062+
{nullptr, DeferredFunctionTemplateOverloadCandidate::Conversion,
11063+
AllowObjCConversionOnExplicit, AllowResultConversion,
11064+
/*AllowExplicit=*/false,
11065+
/*SuppressUserConversions=*/false,
11066+
/*PartialOverloading*/ false,
11067+
/*AggregateCandidateDeduction=*/false},
11068+
FunctionTemplate,
11069+
FoundDecl,
11070+
ActingContext,
11071+
From,
11072+
ToType};
1104711073
}
1104811074

1104911075
static void
1105011076
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11051-
DeferredMethodTemplateOverloadCandidate &&C) {
11077+
DeferredMethodTemplateOverloadCandidate &C) {
1105211078

1105311079
AddMethodTemplateCandidateImmediately(
1105411080
S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext,
@@ -11058,7 +11084,7 @@ AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
1105811084

1105911085
static void
1106011086
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11061-
DeferredFunctionTemplateOverloadCandidate &&C) {
11087+
DeferredFunctionTemplateOverloadCandidate &C) {
1106211088
AddTemplateOverloadCandidateImmediately(
1106311089
S, CandidateSet, C.FunctionTemplate, C.FoundDecl,
1106411090
/*ExplicitTemplateArgs=*/nullptr, C.Args, C.SuppressUserConversions,
@@ -11068,23 +11094,38 @@ AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
1106811094

1106911095
static void
1107011096
AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
11071-
DeferredConversionTemplateOverloadCandidate &&C) {
11097+
DeferredConversionTemplateOverloadCandidate &C) {
1107211098
return AddTemplateConversionCandidateImmediately(
1107311099
S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, C.From,
1107411100
C.ToType, C.AllowObjCConversionOnExplicit, C.AllowExplicit,
1107511101
C.AllowResultConversion);
1107611102
}
1107711103

1107811104
void OverloadCandidateSet::InjectNonDeducedTemplateCandidates(Sema &S) {
11079-
Candidates.reserve(Candidates.size() + DeferredCandidates.size());
11080-
for (auto &&Elem : DeferredCandidates) {
11081-
std::visit(
11082-
[&](auto &&Cand) {
11083-
AddTemplateOverloadCandidate(S, *this, std::move(Cand));
11084-
},
11085-
Elem);
11105+
Candidates.reserve(Candidates.size() + DeferredCandidatesCount);
11106+
DeferredTemplateOverloadCandidate *Cand = FirstDeferredCandidate;
11107+
while (Cand) {
11108+
switch (Cand->Kind) {
11109+
case DeferredTemplateOverloadCandidate::Function:
11110+
AddTemplateOverloadCandidate(
11111+
S, *this,
11112+
*static_cast<DeferredFunctionTemplateOverloadCandidate *>(Cand));
11113+
break;
11114+
case DeferredTemplateOverloadCandidate::Method:
11115+
AddTemplateOverloadCandidate(
11116+
S, *this,
11117+
*static_cast<DeferredMethodTemplateOverloadCandidate *>(Cand));
11118+
break;
11119+
case DeferredTemplateOverloadCandidate::Conversion:
11120+
AddTemplateOverloadCandidate(
11121+
S, *this,
11122+
*static_cast<DeferredConversionTemplateOverloadCandidate *>(Cand));
11123+
break;
11124+
}
11125+
Cand = Cand->Next;
1108611126
}
11087-
DeferredCandidates.clear();
11127+
FirstDeferredCandidate = nullptr;
11128+
DeferredCandidatesCount = 0;
1108811129
}
1108911130

1109011131
OverloadingResult
@@ -11147,10 +11188,10 @@ OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S,
1114711188
iterator &Best) {
1114811189

1114911190
assert(shouldDeferTemplateArgumentDeduction(S.getLangOpts()) ||
11150-
DeferredCandidates.empty() &&
11191+
DeferredCandidatesCount == 0 &&
1115111192
"Unexpected deferred template candidate");
1115211193

11153-
bool TwoPhaseResolution = !DeferredCandidates.empty();
11194+
bool TwoPhaseResolution = DeferredCandidatesCount != 0;
1115411195

1115511196
if (TwoPhaseResolution) {
1115611197

@@ -11261,7 +11302,7 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl(
1126111302

1126211303
OverloadingResult R = ResultForBestCandidate(Best);
1126311304

11264-
if (DeferredCandidates.empty() && !EquivalentCands.empty())
11305+
if (!EquivalentCands.empty())
1126511306
S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
1126611307
EquivalentCands);
1126711308
return R;

0 commit comments

Comments
 (0)