Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2019-08-17 15:30:10 -07:00
2 changed files with 152 additions and 61 deletions

View File

@@ -118,7 +118,11 @@ BuiltinUnit::BuiltinUnit(ModuleDecl &M)
SourceFile::~SourceFile() = default;
class SourceFile::LookupCache {
/// A utility for caching global lookups into SourceFiles and modules of
/// SourceFiles. This is used for lookup of top-level declarations, as well
/// as operator lookup (which looks into types) and AnyObject dynamic lookup
/// (which looks at all class members).
class swift::SourceLookupCache {
/// A lookup map for value decls. When declarations are added they are added
/// under all variants of the name they can be found under.
class DeclMap {
@@ -146,13 +150,14 @@ class SourceFile::LookupCache {
bool MemberCachePopulated = false;
template<typename Range>
void doPopulateCache(Range decls, bool onlyOperators);
void addToMemberCache(DeclRange decls);
void populateMemberCache(const SourceFile &SF);
void addToUnqualifiedLookupCache(Range decls, bool onlyOperators);
template<typename Range>
void addToMemberCache(Range decls);
public:
typedef ModuleDecl::AccessPathTy AccessPathTy;
LookupCache(const SourceFile &SF);
SourceLookupCache(const SourceFile &SF);
SourceLookupCache(const ModuleDecl &Mod);
/// Throw away as much memory as possible.
void invalidate();
@@ -164,19 +169,18 @@ public:
VisibleDeclConsumer &Consumer,
NLKind LookupKind);
void populateMemberCache(const SourceFile &SF);
void populateMemberCache(const ModuleDecl &Mod);
void lookupClassMembers(AccessPathTy AccessPath,
VisibleDeclConsumer &consumer,
const SourceFile &SF);
VisibleDeclConsumer &consumer);
void lookupClassMember(AccessPathTy accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results,
const SourceFile &SF);
SmallVectorImpl<ValueDecl*> &results);
SmallVector<ValueDecl *, 0> AllVisibleValues;
};
using SourceLookupCache = SourceFile::LookupCache;
SourceLookupCache &SourceFile::getCache() const {
if (!Cache) {
const_cast<SourceFile *>(this)->Cache =
@@ -186,8 +190,8 @@ SourceLookupCache &SourceFile::getCache() const {
}
template<typename Range>
void SourceLookupCache::doPopulateCache(Range decls,
bool onlyOperators) {
void SourceLookupCache::addToUnqualifiedLookupCache(Range decls,
bool onlyOperators) {
for (Decl *D : decls) {
if (auto *VD = dyn_cast<ValueDecl>(D)) {
if (onlyOperators ? VD->isOperator() : VD->hasName()) {
@@ -198,7 +202,7 @@ void SourceLookupCache::doPopulateCache(Range decls,
if (auto *NTD = dyn_cast<NominalTypeDecl>(D))
if (!NTD->hasUnparsedMembers() || NTD->maybeHasOperatorDeclarations())
doPopulateCache(NTD->getMembers(), true);
addToUnqualifiedLookupCache(NTD->getMembers(), true);
// Avoid populating the cache with the members of invalid extension
// declarations. These members can be used to point validation inside of
@@ -207,50 +211,71 @@ void SourceLookupCache::doPopulateCache(Range decls,
if (auto *ED = dyn_cast<ExtensionDecl>(D))
if (!ED->hasUnparsedMembers() || ED->maybeHasOperatorDeclarations())
doPopulateCache(ED->getMembers(), true);
addToUnqualifiedLookupCache(ED->getMembers(), true);
}
}
void SourceLookupCache::populateMemberCache(const SourceFile &SF) {
for (const Decl *D : SF.Decls) {
if (const auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
if (!NTD->hasUnparsedMembers() ||
NTD->maybeHasNestedClassDeclarations() ||
NTD->mayContainMembersAccessedByDynamicLookup())
addToMemberCache(NTD->getMembers());
} else if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
if (!ED->hasUnparsedMembers() ||
ED->maybeHasNestedClassDeclarations() ||
ED->mayContainMembersAccessedByDynamicLookup())
addToMemberCache(ED->getMembers());
}
if (MemberCachePopulated)
return;
FrontendStatsTracer tracer(SF.getASTContext().Stats,
"populate-source-file-class-member-cache");
addToMemberCache(SF.Decls);
MemberCachePopulated = true;
}
void SourceLookupCache::populateMemberCache(const ModuleDecl &Mod) {
if (MemberCachePopulated)
return;
FrontendStatsTracer tracer(Mod.getASTContext().Stats,
"populate-module-class-member-cache");
for (const FileUnit *file : Mod.getFiles()) {
auto &SF = *cast<SourceFile>(file);
addToMemberCache(SF.Decls);
}
MemberCachePopulated = true;
}
void SourceLookupCache::addToMemberCache(DeclRange decls) {
template <typename Range>
void SourceLookupCache::addToMemberCache(Range decls) {
for (Decl *D : decls) {
auto VD = dyn_cast<ValueDecl>(D);
if (!VD)
continue;
if (auto NTD = dyn_cast<NominalTypeDecl>(VD)) {
assert(!VD->canBeAccessedByDynamicLookup() &&
"inner types cannot be accessed by dynamic lookup");
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
if (!NTD->hasUnparsedMembers() ||
NTD->maybeHasNestedClassDeclarations() ||
NTD->mayContainMembersAccessedByDynamicLookup())
addToMemberCache(NTD->getMembers());
} else if (VD->canBeAccessedByDynamicLookup()) {
ClassMembers.add(VD);
} else if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
if (!ED->hasUnparsedMembers() ||
ED->maybeHasNestedClassDeclarations() ||
ED->mayContainMembersAccessedByDynamicLookup())
addToMemberCache(ED->getMembers());
} else if (auto *VD = dyn_cast<ValueDecl>(D)) {
if (VD->canBeAccessedByDynamicLookup())
ClassMembers.add(VD);
}
}
}
/// Populate our cache on the first name lookup.
SourceLookupCache::LookupCache(const SourceFile &SF) {
doPopulateCache(llvm::makeArrayRef(SF.Decls), false);
SourceLookupCache::SourceLookupCache(const SourceFile &SF) {
FrontendStatsTracer tracer(SF.getASTContext().Stats,
"source-file-populate-cache");
addToUnqualifiedLookupCache(SF.Decls, false);
}
SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
FrontendStatsTracer tracer(M.getASTContext().Stats,
"module-populate-cache");
for (const FileUnit *file : M.getFiles()) {
auto &SF = *cast<SourceFile>(file);
addToUnqualifiedLookupCache(SF.Decls, false);
}
}
void SourceLookupCache::lookupValue(AccessPathTy AccessPath, DeclName Name,
@@ -295,11 +320,7 @@ void SourceLookupCache::lookupVisibleDecls(AccessPathTy AccessPath,
}
void SourceLookupCache::lookupClassMembers(AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
const SourceFile &SF) {
if (!MemberCachePopulated)
populateMemberCache(SF);
VisibleDeclConsumer &consumer) {
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
if (!accessPath.empty()) {
@@ -333,11 +354,7 @@ void SourceLookupCache::lookupClassMembers(AccessPathTy accessPath,
void SourceLookupCache::lookupClassMember(AccessPathTy accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results,
const SourceFile &SF) {
if (!MemberCachePopulated)
populateMemberCache(SF);
SmallVectorImpl<ValueDecl*> &results) {
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
auto iter = ClassMembers.find(name);
@@ -395,6 +412,7 @@ void ModuleDecl::addFile(FileUnit &newFile) {
cast<SourceFile>(newFile).Kind == SourceFileKind::Library ||
cast<SourceFile>(newFile).Kind == SourceFileKind::SIL);
Files.push_back(&newFile);
clearLookupCache();
}
void ModuleDecl::removeFile(FileUnit &existingFile) {
@@ -407,15 +425,41 @@ void ModuleDecl::removeFile(FileUnit &existingFile) {
// Adjust for the std::reverse_iterator offset.
++I;
Files.erase(I.base());
clearLookupCache();
}
#define FORWARD(name, args) \
for (const FileUnit *file : getFiles()) \
file->name args;
SourceLookupCache &ModuleDecl::getSourceLookupCache() const {
if (!Cache) {
const_cast<ModuleDecl *>(this)->Cache =
llvm::make_unique<SourceLookupCache>(*this);
}
return *Cache;
}
static bool isParsedModule(const ModuleDecl *mod) {
// FIXME: If we ever get mixed modules that contain both SourceFiles and other
// kinds of file units, this will break; there all callers of this function should
// themselves assert that all file units in the module are SourceFiles when this
// function returns true.
auto files = mod->getFiles();
return (files.size() > 0 &&
isa<SourceFile>(files[0]) &&
cast<SourceFile>(files[0])->Kind != SourceFileKind::SIL);
}
void ModuleDecl::lookupValue(AccessPathTy AccessPath, DeclName Name,
NLKind LookupKind,
SmallVectorImpl<ValueDecl*> &Result) const {
if (isParsedModule(this)) {
FrontendStatsTracer tracer(getASTContext().Stats, "source-file-lookup-value");
getSourceLookupCache().lookupValue(AccessPath, Name, LookupKind, Result);
return;
}
FORWARD(lookupValue, (AccessPath, Name, LookupKind, Result));
}
@@ -453,9 +497,9 @@ void ModuleDecl::lookupMember(SmallVectorImpl<ValueDecl*> &results,
auto lookupResults = nominal->lookupDirect(name);
// Filter out declarations from other modules.
std::copy_if(lookupResults.begin(), lookupResults.end(),
std::back_inserter(results),
[this](const ValueDecl *VD) -> bool {
llvm::copy_if(lookupResults,
std::back_inserter(results),
[this](const ValueDecl *VD) -> bool {
return VD->getModuleContext() == this;
});
@@ -523,8 +567,12 @@ void SourceFile::lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name,
}
void ModuleDecl::lookupVisibleDecls(AccessPathTy AccessPath,
VisibleDeclConsumer &Consumer,
NLKind LookupKind) const {
VisibleDeclConsumer &Consumer,
NLKind LookupKind) const {
if (isParsedModule(this))
return getSourceLookupCache().lookupVisibleDecls(
AccessPath, Consumer, LookupKind);
FORWARD(lookupVisibleDecls, (AccessPath, Consumer, LookupKind));
}
@@ -535,25 +583,45 @@ void SourceFile::lookupVisibleDecls(ModuleDecl::AccessPathTy AccessPath,
}
void ModuleDecl::lookupClassMembers(AccessPathTy accessPath,
VisibleDeclConsumer &consumer) const {
VisibleDeclConsumer &consumer) const {
if (isParsedModule(this)) {
auto &cache = getSourceLookupCache();
cache.populateMemberCache(*this);
cache.lookupClassMembers(accessPath, consumer);
return;
}
FORWARD(lookupClassMembers, (accessPath, consumer));
}
void SourceFile::lookupClassMembers(ModuleDecl::AccessPathTy accessPath,
VisibleDeclConsumer &consumer) const {
getCache().lookupClassMembers(accessPath, consumer, *this);
auto &cache = getCache();
cache.populateMemberCache(*this);
cache.lookupClassMembers(accessPath, consumer);
}
void ModuleDecl::lookupClassMember(AccessPathTy accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results) const {
if (isParsedModule(this)) {
FrontendStatsTracer tracer(getASTContext().Stats, "source-file-lookup-class-member");
auto &cache = getSourceLookupCache();
cache.populateMemberCache(*this);
cache.lookupClassMember(accessPath, name, results);
return;
}
FORWARD(lookupClassMember, (accessPath, name, results));
}
void SourceFile::lookupClassMember(ModuleDecl::AccessPathTy accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results) const {
getCache().lookupClassMember(accessPath, name, results, *this);
FrontendStatsTracer tracer(getASTContext().Stats, "source-file-lookup-class-member");
auto &cache = getCache();
cache.populateMemberCache(*this);
cache.lookupClassMember(accessPath, name, results);
}
void SourceFile::lookupObjCMethods(
@@ -1563,7 +1631,18 @@ bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const {
return !isImportedBy(module, getParentModule());
}
void ModuleDecl::clearLookupCache() {
if (!Cache)
return;
// Abandon any current cache. We'll rebuild it on demand.
Cache->invalidate();
Cache.reset();
}
void SourceFile::clearLookupCache() {
getParentModule()->clearLookupCache();
if (!Cache)
return;