Skip to content

Commit 4e42f03

Browse files
committed
Switch operator lookup over to using SourceLookupCache
Switch the direct operator lookup logic over to querying the SourceLookupCache, then switch the main operator lookup logic over to calling the direct lookup logic rather than querying the operator maps on the SourceFile. This then allows us to remove the SourceFile operator maps, in addition to the logic from NameBinding that populated them. This requires redeclaration checking to be implemented separately. Finally, to compensate for the caching that the old operator maps were providing for imported results, turn the operator lookup requests into cached requests.
1 parent 6f21263 commit 4e42f03

File tree

9 files changed

+122
-146
lines changed

9 files changed

+122
-146
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>,
4949
PropertyWrapperMutability)
5050
SWIFT_TYPEID_NAMED(ParamDecl *, ParamDecl)
5151
SWIFT_TYPEID_NAMED(PatternBindingEntry *, PatternBindingEntry)
52+
SWIFT_TYPEID_NAMED(PostfixOperatorDecl *, PostfixOperatorDecl)
5253
SWIFT_TYPEID_NAMED(PrecedenceGroupDecl *, PrecedenceGroupDecl)
54+
SWIFT_TYPEID_NAMED(PrefixOperatorDecl *, PrefixOperatorDecl)
5355
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)
5456
SWIFT_TYPEID_NAMED(SourceFile *, SourceFile)
5557
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class OpaqueTypeDecl;
4343
class PatternBindingEntry;
4444
class ParamDecl;
4545
enum class ParamSpecifier : uint8_t;
46+
class PostfixOperatorDecl;
4647
class PrecedenceGroupDecl;
48+
class PrefixOperatorDecl;
4749
struct PropertyWrapperBackingPropertyInfo;
4850
struct PropertyWrapperTypeInfo;
4951
enum class CtorInitializerKind;

include/swift/AST/Module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ class OverlayFile;
165165
///
166166
/// \sa FileUnit
167167
class ModuleDecl : public DeclContext, public TypeDecl {
168+
friend class DirectOperatorLookupRequest;
169+
friend class DirectPrecedenceGroupLookupRequest;
170+
168171
public:
169172
typedef ArrayRef<Located<Identifier>> AccessPathTy;
170173
typedef std::pair<ModuleDecl::AccessPathTy, ModuleDecl*> ImportedModule;

include/swift/AST/NameLookupRequests.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,19 +598,23 @@ template <typename OperatorType>
598598
class LookupOperatorRequest
599599
: public SimpleRequest<LookupOperatorRequest<OperatorType>,
600600
OperatorType *(OperatorLookupDescriptor),
601-
CacheKind::Uncached> {
601+
CacheKind::Cached> {
602602
using SimpleRequest<LookupOperatorRequest<OperatorType>,
603603
OperatorType *(OperatorLookupDescriptor),
604-
CacheKind::Uncached>::SimpleRequest;
604+
CacheKind::Cached>::SimpleRequest;
605605

606606
private:
607607
friend SimpleRequest<LookupOperatorRequest<OperatorType>,
608608
OperatorType *(OperatorLookupDescriptor),
609-
CacheKind::Uncached>;
609+
CacheKind::Cached>;
610610

611611
// Evaluation.
612612
OperatorType *
613613
evaluate(Evaluator &evaluator, OperatorLookupDescriptor desc) const;
614+
615+
public:
616+
// Cached.
617+
bool isCached() const { return true; }
614618
};
615619

616620
using LookupPrefixOperatorRequest = LookupOperatorRequest<PrefixOperatorDecl>;

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ SWIFT_REQUEST(NameLookup, UnqualifiedLookupRequest,
8787

8888
SWIFT_REQUEST(NameLookup, LookupPrefixOperatorRequest,
8989
PrefixOperatorDecl *(OperatorLookupDescriptor),
90-
Uncached, NoLocationInfo)
90+
Cached, NoLocationInfo)
9191
SWIFT_REQUEST(NameLookup, LookupInfixOperatorRequest,
9292
InfixOperatorDecl *(OperatorLookupDescriptor),
93-
Uncached, NoLocationInfo)
93+
Cached, NoLocationInfo)
9494
SWIFT_REQUEST(NameLookup, LookupPostfixOperatorRequest,
9595
PostfixOperatorDecl *(OperatorLookupDescriptor),
96-
Uncached, NoLocationInfo)
96+
Cached, NoLocationInfo)
9797
SWIFT_REQUEST(NameLookup, LookupPrecedenceGroupRequest,
9898
PrecedenceGroupDecl *(OperatorLookupDescriptor),
99-
Uncached, NoLocationInfo)
99+
Cached, NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,6 @@ class SourceFile final : public FileUnit {
311311
/// List of Objective-C member conflicts we have found during type checking.
312312
std::vector<ObjCMethodConflict> ObjCMethodConflicts;
313313

314-
template <typename T>
315-
using OperatorMap = llvm::DenseMap<Identifier,llvm::PointerIntPair<T,1,bool>>;
316-
317-
OperatorMap<InfixOperatorDecl*> InfixOperators;
318-
OperatorMap<PostfixOperatorDecl*> PostfixOperators;
319-
OperatorMap<PrefixOperatorDecl*> PrefixOperators;
320-
OperatorMap<PrecedenceGroupDecl*> PrecedenceGroups;
321-
322314
/// Describes what kind of file this is, which can affect some type checking
323315
/// and other behavior.
324316
const SourceFileKind Kind;

lib/AST/Module.cpp

Lines changed: 35 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,9 +1026,6 @@ LookupConformanceInModuleRequest::evaluate(
10261026
}
10271027

10281028
namespace {
1029-
template <typename T>
1030-
using OperatorMap = SourceFile::OperatorMap<T>;
1031-
10321029
template <typename T>
10331030
struct OperatorLookup {
10341031
// Don't fold this into the static_assert: this would trigger an MSVC bug
@@ -1039,7 +1036,6 @@ namespace {
10391036

10401037
template <>
10411038
struct OperatorLookup<PrefixOperatorDecl> {
1042-
constexpr static auto map_ptr = &SourceFile::PrefixOperators;
10431039
static PrefixOperatorDecl *lookup(Evaluator &eval,
10441040
const OperatorLookupDescriptor &desc) {
10451041
// We can return the first prefix operator. All prefix operators of the
@@ -1052,7 +1048,6 @@ namespace {
10521048

10531049
template <>
10541050
struct OperatorLookup<InfixOperatorDecl> {
1055-
constexpr static auto map_ptr = &SourceFile::InfixOperators;
10561051
static InfixOperatorDecl *lookup(Evaluator &eval,
10571052
const OperatorLookupDescriptor &desc) {
10581053
// Return the first result if it exists.
@@ -1064,7 +1059,6 @@ namespace {
10641059

10651060
template <>
10661061
struct OperatorLookup<PostfixOperatorDecl> {
1067-
constexpr static auto map_ptr = &SourceFile::PostfixOperators;
10681062
static PostfixOperatorDecl *lookup(Evaluator &eval,
10691063
const OperatorLookupDescriptor &desc) {
10701064
// We can return the first postfix operator. All postfix operators of the
@@ -1077,7 +1071,6 @@ namespace {
10771071

10781072
template <>
10791073
struct OperatorLookup<PrecedenceGroupDecl> {
1080-
constexpr static auto map_ptr = &SourceFile::PrecedenceGroups;
10811074
static PrecedenceGroupDecl *lookup(Evaluator &eval,
10821075
const OperatorLookupDescriptor &desc) {
10831076
// Return the first result if it exists.
@@ -1172,6 +1165,10 @@ static Optional<OP_DECL *>
11721165
lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11731166
Identifier Name, bool includePrivate,
11741167
bool isCascading) {
1168+
auto &eval = File.getASTContext().evaluator;
1169+
auto desc = OperatorLookupDescriptor::forFile(const_cast<FileUnit *>(&File),
1170+
Name, isCascading,
1171+
/*diagLoc*/ SourceLoc());
11751172
switch (File.getKind()) {
11761173
case FileUnitKind::Builtin:
11771174
// The Builtin module declares no operators.
@@ -1180,23 +1177,16 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11801177
break;
11811178
case FileUnitKind::SerializedAST:
11821179
case FileUnitKind::ClangModule:
1183-
case FileUnitKind::DWARFModule: {
1184-
auto &eval = File.getASTContext().evaluator;
1185-
auto desc = OperatorLookupDescriptor::forFile(const_cast<FileUnit *>(&File),
1186-
Name, isCascading,
1187-
/*diagLoc*/ SourceLoc());
1180+
case FileUnitKind::DWARFModule:
11881181
return OperatorLookup<OP_DECL>::lookup(eval, desc);
11891182
}
1190-
}
11911183

11921184
auto &SF = cast<SourceFile>(File);
11931185
assert(SF.ASTStage >= SourceFile::NameBound);
11941186

1195-
// Look for an operator declaration in the current module.
1196-
const auto OP_MAP = OperatorLookup<OP_DECL>::map_ptr;
1197-
auto found = (SF.*OP_MAP).find(Name);
1198-
if (found != (SF.*OP_MAP).end() && (includePrivate || found->second.getInt()))
1199-
return found->second.getPointer();
1187+
// Check if the decl exists on the file.
1188+
if (auto *op = OperatorLookup<OP_DECL>::lookup(eval, desc))
1189+
return op;
12001190

12011191
// Look for imported operator decls.
12021192
// Record whether they come from re-exported modules.
@@ -1224,24 +1214,16 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
12241214
importedOperators[op] |= isExported;
12251215
}
12261216

1227-
typename OperatorMap<OP_DECL *>::mapped_type result = { nullptr, true };
1228-
1217+
llvm::PointerIntPair<OP_DECL *, 1, /*isPrivate*/ bool> result = {nullptr,
1218+
true};
1219+
12291220
if (!importedOperators.empty()) {
12301221
auto start = checkOperatorConflicts(SF, Loc, importedOperators);
12311222
if (start == importedOperators.end())
12321223
return None;
12331224
result = { start->first, start->second };
12341225
}
12351226

1236-
if (includePrivate) {
1237-
// Cache the mapping so we don't need to troll imports next time.
1238-
// It's not safe to cache the non-private results because we didn't search
1239-
// private imports there, but in most non-private cases the result will
1240-
// be cached in the final lookup.
1241-
auto &mutableOpMap = const_cast<OperatorMap<OP_DECL *> &>(SF.*OP_MAP);
1242-
mutableOpMap[Name] = result;
1243-
}
1244-
12451227
if (includePrivate || result.getInt())
12461228
return result.getPointer();
12471229
return nullptr;
@@ -1311,9 +1293,18 @@ TinyPtrVector<OperatorDecl *>
13111293
DirectOperatorLookupRequest::evaluate(Evaluator &evaluator,
13121294
OperatorLookupDescriptor descriptor,
13131295
OperatorFixity fixity) const {
1314-
// Query each file.
1315-
// TODO: Module-level caching.
1296+
// For a parsed module, we can check the source cache on the module rather
1297+
// than doing an O(N) search over the source files.
13161298
TinyPtrVector<OperatorDecl *> results;
1299+
if (auto module = descriptor.getModule()) {
1300+
if (isParsedModule(module)) {
1301+
module->getSourceLookupCache().lookupOperator(descriptor.name, fixity,
1302+
results);
1303+
return results;
1304+
}
1305+
}
1306+
1307+
// Otherwise query each file.
13171308
for (auto *file : descriptor.getFiles())
13181309
file->lookupOperatorDirect(descriptor.name, fixity, results);
13191310

@@ -1323,40 +1314,24 @@ DirectOperatorLookupRequest::evaluate(Evaluator &evaluator,
13231314
void SourceFile::lookupOperatorDirect(
13241315
Identifier name, OperatorFixity fixity,
13251316
TinyPtrVector<OperatorDecl *> &results) const {
1326-
OperatorDecl *op = nullptr;
1327-
switch (fixity) {
1328-
case OperatorFixity::Infix: {
1329-
auto result = InfixOperators.find(name);
1330-
if (result != InfixOperators.end())
1331-
op = result->second.getPointer();
1332-
break;
1333-
}
1334-
case OperatorFixity::Postfix: {
1335-
auto result = PostfixOperators.find(name);
1336-
if (result != PostfixOperators.end())
1337-
op = result->second.getPointer();
1338-
break;
1339-
}
1340-
case OperatorFixity::Prefix: {
1341-
auto result = PrefixOperators.find(name);
1342-
if (result != PrefixOperators.end())
1343-
op = result->second.getPointer();
1344-
break;
1345-
}
1346-
}
1347-
1348-
// We currently can use the operator maps to cache lookup results from other
1349-
// modules. Make sure we only return results from the source file.
1350-
if (op && op->getDeclContext()->getParentSourceFile() == this)
1351-
results.push_back(op);
1317+
getCache().lookupOperator(name, fixity, results);
13521318
}
13531319

13541320
TinyPtrVector<PrecedenceGroupDecl *>
13551321
DirectPrecedenceGroupLookupRequest::evaluate(
13561322
Evaluator &evaluator, OperatorLookupDescriptor descriptor) const {
1357-
// Query each file.
1358-
// TODO: Module-level caching.
1323+
// For a parsed module, we can check the source cache on the module rather
1324+
// than doing an O(N) search over the source files.
13591325
TinyPtrVector<PrecedenceGroupDecl *> results;
1326+
if (auto module = descriptor.getModule()) {
1327+
if (isParsedModule(module)) {
1328+
module->getSourceLookupCache().lookupPrecedenceGroup(descriptor.name,
1329+
results);
1330+
return results;
1331+
}
1332+
}
1333+
1334+
// Otherwise query each file.
13601335
for (auto *file : descriptor.getFiles())
13611336
file->lookupPrecedenceGroupDirect(descriptor.name, results);
13621337

@@ -1365,15 +1340,7 @@ DirectPrecedenceGroupLookupRequest::evaluate(
13651340

13661341
void SourceFile::lookupPrecedenceGroupDirect(
13671342
Identifier name, TinyPtrVector<PrecedenceGroupDecl *> &results) const {
1368-
auto result = PrecedenceGroups.find(name);
1369-
if (result == PrecedenceGroups.end())
1370-
return;
1371-
1372-
// We currently can use the operator maps to cache lookup results from other
1373-
// modules. Make sure we only return results from the source file.
1374-
auto *group = result->second.getPointer();
1375-
if (group->getDeclContext()->getParentSourceFile() == this)
1376-
results.push_back(group);
1343+
getCache().lookupPrecedenceGroup(name, results);
13771344
}
13781345

13791346
void ModuleDecl::getImportedModules(SmallVectorImpl<ImportedModule> &modules,

0 commit comments

Comments
 (0)