Skip to content

Commit 826d7c7

Browse files
committed
Swift: preload extension indexes
Finding each extension declaration separately within its parent seemed to create an `O(n^2)` noticeable performance problem. This is solved by preloading indexes and storing them in a map, so as to iterate through the parent of an extension only once per parent instead of once per extension.
1 parent 1465919 commit 826d7c7

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

swift/extractor/mangler/SwiftMangler.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,26 +98,36 @@ SwiftMangledName SwiftMangler::visitExtensionDecl(const swift::ExtensionDecl* de
9898
}
9999

100100
auto parent = getParent(decl);
101-
unsigned index = 0;
101+
return initMangled(decl) << fetch(parent) << getExtensionIndex(decl, parent);
102+
}
103+
104+
unsigned SwiftMangler::getExtensionIndex(const swift::ExtensionDecl* decl,
105+
const swift::Decl* parent) {
106+
if (auto found = preloadedExtensionIndexes.extract(decl)) {
107+
return found.mapped();
108+
}
102109
if (auto parentModule = llvm::dyn_cast<swift::ModuleDecl>(parent)) {
103-
llvm::SmallVector<swift::Decl*> parentDecls;
104-
parentModule->getTopLevelDecls(parentDecls);
105-
auto found = std::find(std::begin(parentDecls), std::end(parentDecls), decl);
106-
assert(found != std::end(parentDecls));
107-
index = found - std::begin(parentDecls);
110+
llvm::SmallVector<swift::Decl*> siblings;
111+
parentModule->getTopLevelDecls(siblings);
112+
indexExtensions(siblings);
108113
} else if (auto iterableParent = llvm::dyn_cast<swift::IterableDeclContext>(parent)) {
109-
auto parentDecls = iterableParent->getAllMembers();
110-
auto found = std::find(std::begin(parentDecls), std::end(parentDecls), decl);
111-
assert(found != std::end(parentDecls));
112-
index = found - std::begin(parentDecls);
114+
indexExtensions(iterableParent->getAllMembers());
113115
} else {
114116
assert(false && "non-local context must be module or iterable decl context");
115117
}
118+
auto found = preloadedExtensionIndexes.extract(decl);
119+
assert(found && "extension not found within parent");
120+
return found.mapped();
121+
}
116122

117-
auto ret = initMangled(decl);
118-
ret << fetch(parent);
119-
ret << index;
120-
return ret;
123+
void SwiftMangler::indexExtensions(llvm::ArrayRef<swift::Decl*> siblings) {
124+
auto index = 0u;
125+
for (auto sibling : siblings) {
126+
if (sibling->getKind() == swift::DeclKind::Extension) {
127+
preloadedExtensionIndexes.emplace(sibling, index);
128+
}
129+
++index;
130+
}
121131
}
122132

123133
SwiftMangledName SwiftMangler::visitGenericTypeDecl(const swift::GenericTypeDecl* decl) {

swift/extractor/mangler/SwiftMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
102102

103103
swift::Mangle::ASTMangler mangler;
104104
SwiftDispatcher& dispatcher;
105+
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
106+
void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
107+
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
105108
};
106109

107110
} // namespace codeql

0 commit comments

Comments
 (0)