Skip to content

Commit 7e5ecfd

Browse files
authored
Merge pull request #66257 from DougGregor/member-lookup-macro-expansion-performance
Member lookup macro expansion performance
2 parents 630a7fc + 2f41499 commit 7e5ecfd

7 files changed

+347
-20
lines changed

include/swift/AST/NameLookupRequests.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/FileUnit.h"
2323
#include "swift/AST/Identifier.h"
2424
#include "swift/AST/NameLookup.h"
25+
#include "swift/AST/TypeOrExtensionDecl.h"
2526
#include "swift/Basic/Statistic.h"
2627
#include "llvm/ADT/Hashing.h"
2728
#include "llvm/ADT/TinyPtrVector.h"
@@ -37,6 +38,7 @@ class GenericContext;
3738
class GenericParamList;
3839
class LookupResult;
3940
enum class NLKind;
41+
class PotentialMacroExpansions;
4042
class SourceLoc;
4143
class TypeAliasDecl;
4244
class TypeDecl;
@@ -889,6 +891,27 @@ class HasDynamicCallableAttributeRequest
889891
bool isCached() const { return true; }
890892
};
891893

894+
/// Determine the potential macro expansions for a given type or extension
895+
/// context.
896+
class PotentialMacroExpansionsInContextRequest
897+
: public SimpleRequest<
898+
PotentialMacroExpansionsInContextRequest,
899+
PotentialMacroExpansions(TypeOrExtensionDecl),
900+
RequestFlags::Cached> {
901+
public:
902+
using SimpleRequest::SimpleRequest;
903+
904+
private:
905+
friend SimpleRequest;
906+
907+
// Evaluation.
908+
PotentialMacroExpansions evaluate(
909+
Evaluator &evaluator, TypeOrExtensionDecl container) const;
910+
911+
public:
912+
bool isCached() const { return true; }
913+
};
914+
892915
#define SWIFT_TYPEID_ZONE NameLookup
893916
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
894917
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,5 @@ SWIFT_REQUEST(NameLookup, HasDynamicMemberLookupAttributeRequest,
107107
bool(NominalTypeDecl *), Cached, NoLocationInfo)
108108
SWIFT_REQUEST(NameLookup, HasDynamicCallableAttributeRequest,
109109
bool(NominalTypeDecl *), Cached, NoLocationInfo)
110+
SWIFT_REQUEST(NameLookup, PotentialMacroExpansionsInContextRequest,
111+
PotentialMacroExpansions(TypeOrExtension), Cached, NoLocationInfo)
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
//===--- PotentialMacroExpansions.h -----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines a structure (\c PotentialMacroExpansions) to track
14+
// potential macro expansions within a given context.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
#ifndef SWIFT_AST_POTENTIAL_MACRO_EXPANSIONS_H
18+
#define SWIFT_AST_POTENTIAL_MACRO_EXPANSIONS_H
19+
20+
#include "swift/AST/Identifier.h"
21+
#include "llvm/ADT/PointerIntPair.h"
22+
#include "llvm/ADT/SmallPtrSet.h"
23+
24+
namespace swift {
25+
26+
/// Describes the potential macro expansions within a given type or
27+
/// extension context.
28+
class PotentialMacroExpansions {
29+
enum {
30+
/// Whether there are any expanded macros.
31+
AnyExpandedMacros = 0x01,
32+
33+
/// Whether any of the expanded macros introduces arbitrary names.
34+
IntroducesArbitraryNames = 0x02,
35+
};
36+
37+
using NameSet = llvm::SmallPtrSet<DeclName, 4>;
38+
39+
/// Storage for the set of potential macro expansions.
40+
llvm::PointerIntPair<NameSet *, 2, unsigned> Storage;
41+
42+
/// Retrieve a pointer to the name set if there is one.
43+
const NameSet *getIntroducedNamesIfAvailable() const {
44+
return Storage.getPointer();
45+
}
46+
47+
/// Get or create a nam
48+
NameSet &getOrCreateIntroducedNames() {
49+
if (auto nameSet = Storage.getPointer())
50+
return *nameSet;
51+
52+
// Allocate a new set of introduced names.
53+
auto nameSet = new NameSet();
54+
Storage.setPointer(nameSet);
55+
return *nameSet;
56+
}
57+
58+
public:
59+
PotentialMacroExpansions() : Storage() { }
60+
61+
PotentialMacroExpansions(const PotentialMacroExpansions &other)
62+
: Storage(nullptr, other.Storage.getInt())
63+
{
64+
if (auto otherNameSet = other.getIntroducedNamesIfAvailable()) {
65+
Storage.setPointer(new NameSet(*otherNameSet));
66+
}
67+
}
68+
69+
PotentialMacroExpansions(PotentialMacroExpansions &&other)
70+
: Storage(other.Storage)
71+
{
72+
other.Storage.setPointer(nullptr);
73+
}
74+
75+
PotentialMacroExpansions &operator=(const PotentialMacroExpansions &other) {
76+
PotentialMacroExpansions tmp(other);
77+
swap(tmp, *this);
78+
return *this;
79+
}
80+
81+
PotentialMacroExpansions &operator=(PotentialMacroExpansions &&other) {
82+
if (&other != this) {
83+
Storage = other.Storage;
84+
other.Storage.setPointer(nullptr);
85+
}
86+
return *this;
87+
}
88+
89+
~PotentialMacroExpansions() {
90+
delete getIntroducedNamesIfAvailable();
91+
}
92+
93+
/// Whether there are any expanded macros in this context.
94+
explicit operator bool() const { return hasAnyExpandedMacro(); }
95+
96+
/// Whether there are any expanded macros in this context.
97+
bool hasAnyExpandedMacro() const {
98+
return Storage.getInt() & AnyExpandedMacros;
99+
}
100+
101+
/// Note that we have expanded a macro.
102+
void noteExpandedMacro() {
103+
Storage.setInt(Storage.getInt() | AnyExpandedMacros);
104+
}
105+
106+
/// Whether any expanded macro introduces arbitrary names.
107+
bool introducesArbitraryNames() const {
108+
return Storage.getInt() & IntroducesArbitraryNames;
109+
}
110+
111+
/// Note that a macro expanded here introduced arbitrary names.
112+
void noteIntroducesArbitraryNames() {
113+
Storage.setInt(Storage.getInt() | IntroducesArbitraryNames);
114+
}
115+
116+
/// Add a new introduced macro name.
117+
void addIntroducedMacroName(DeclName name) {
118+
getOrCreateIntroducedNames().insert(name.getBaseName());
119+
}
120+
121+
/// Determine whether one should expand any macros in this context because
122+
/// they could introduce a declaration with the given name.
123+
bool shouldExpandForName(DeclName name) const {
124+
// If any macro produces arbitraty names, we need to expand it.
125+
if (introducesArbitraryNames())
126+
return true;
127+
128+
auto introducedNames = getIntroducedNamesIfAvailable();
129+
if (!introducedNames)
130+
return false;
131+
132+
return introducedNames->count(name.getBaseName());
133+
}
134+
135+
friend bool operator==(const PotentialMacroExpansions &lhs,
136+
const PotentialMacroExpansions &rhs) {
137+
// Check has-any-expanded-macro and introduces-arbitrary-names together.
138+
if (lhs.Storage.getInt() != rhs.Storage.getInt())
139+
return false;
140+
141+
// If they introduced arbitrary names, ignore the name sets... they are
142+
// the same.
143+
if (lhs.introducesArbitraryNames())
144+
return true;
145+
146+
// Both expanded macros and did not introduce arbitrary names, so we need
147+
// to check the actual names.
148+
auto lhsIntroducedNames = lhs.getIntroducedNamesIfAvailable();
149+
auto rhsIntroducedNames = rhs.getIntroducedNamesIfAvailable();
150+
151+
auto lhsIntroducedNamesCount =
152+
lhsIntroducedNames ? lhsIntroducedNames->size() : 0;
153+
auto rhsIntroducedNamesCount =
154+
rhsIntroducedNames ? rhsIntroducedNames->size() : 0;
155+
if (lhsIntroducedNamesCount != rhsIntroducedNamesCount)
156+
return false;
157+
158+
// Check whether both are empty.
159+
if (lhsIntroducedNamesCount == 0)
160+
return true;
161+
162+
// Make sure all of the names of one are in the other.
163+
for (auto lhsName : *lhsIntroducedNames) {
164+
if (rhsIntroducedNames->count(lhsName) == 0)
165+
return false;
166+
}
167+
168+
return true;
169+
}
170+
171+
friend bool operator!=(const PotentialMacroExpansions &lhs,
172+
const PotentialMacroExpansions &rhs) {
173+
return !(lhs == rhs);
174+
}
175+
176+
friend void swap(
177+
PotentialMacroExpansions &lhs, PotentialMacroExpansions &rhs) {
178+
auto tmpStorage = lhs.Storage;
179+
lhs.Storage = rhs.Storage;
180+
rhs.Storage = tmpStorage;
181+
}
182+
};
183+
184+
}
185+
186+
#endif // SWIFT_AST_POTENTIAL_MACRO_EXPANSIONS_H

include/swift/AST/TypeOrExtensionDecl.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@
2121
#include "swift/AST/TypeAlignments.h"
2222
#include "llvm/ADT/PointerUnion.h"
2323

24+
namespace llvm {
25+
class raw_ostream;
26+
}
27+
2428
namespace swift {
2529

30+
class SourceLoc;
2631
class DeclContext;
2732
class IterableDeclContext;
2833

@@ -51,11 +56,23 @@ struct TypeOrExtensionDecl {
5156
bool isNull() const;
5257
explicit operator bool() const { return !isNull(); }
5358

54-
bool operator==(TypeOrExtensionDecl rhs) { return Decl == rhs.Decl; }
55-
bool operator!=(TypeOrExtensionDecl rhs) { return Decl != rhs.Decl; }
56-
bool operator<(TypeOrExtensionDecl rhs) { return Decl < rhs.Decl; }
59+
friend bool operator==(TypeOrExtensionDecl lhs, TypeOrExtensionDecl rhs) {
60+
return lhs.Decl == rhs.Decl;
61+
}
62+
friend bool operator!=(TypeOrExtensionDecl lhs, TypeOrExtensionDecl rhs) {
63+
return lhs.Decl != rhs.Decl;
64+
}
65+
friend bool operator<(TypeOrExtensionDecl lhs, TypeOrExtensionDecl rhs) {
66+
return lhs.Decl < rhs.Decl;
67+
}
68+
friend llvm::hash_code hash_value(TypeOrExtensionDecl decl) {
69+
return llvm::hash_value(decl.getAsDecl());
70+
}
5771
};
5872

73+
void simple_display(llvm::raw_ostream &out, TypeOrExtensionDecl container);
74+
SourceLoc extractNearestSourceLoc(TypeOrExtensionDecl container);
75+
5976
} // end namespace swift
6077

6178
#endif

lib/AST/Decl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10123,6 +10123,11 @@ void swift::simple_display(llvm::raw_ostream &out,
1012310123
out << " }";
1012410124
}
1012510125

10126+
void swift::simple_display(llvm::raw_ostream &out,
10127+
TypeOrExtensionDecl container) {
10128+
simple_display(out, container.getAsDecl());
10129+
}
10130+
1012610131
void swift::simple_display(llvm::raw_ostream &out, const ValueDecl *decl) {
1012710132
if (decl) decl->dumpRef(out);
1012810133
else out << "(null)";
@@ -10155,6 +10160,11 @@ SourceLoc swift::extractNearestSourceLoc(const Decl *decl) {
1015510160
return extractNearestSourceLoc(decl->getDeclContext());
1015610161
}
1015710162

10163+
SourceLoc swift::extractNearestSourceLoc(TypeOrExtensionDecl container) {
10164+
return extractNearestSourceLoc(container.Decl);
10165+
}
10166+
10167+
1015810168
Optional<BodyAndFingerprint>
1015910169
ParseAbstractFunctionBodyRequest::getCachedResult() const {
1016010170
using BodyKind = AbstractFunctionDecl::BodyKind;

0 commit comments

Comments
 (0)