Skip to content

[CodeCompletion] Lazily populate 'BasicSourceFileInfo' #36168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions include/swift/AST/RawComment.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,51 @@ struct BasicDeclLocs {
LineColumn EndLoc;
};

struct BasicSourceFileInfo {
class BasicSourceFileInfo {
/// If this is non-null, fields other than 'FilePath' hasn't been populated.
/// The 'getInt()' part indicates this instance is constructed with a
/// SourceFile.
llvm::PointerIntPair<const SourceFile *, 1, bool> SFAndIsFromSF;

StringRef FilePath;
Fingerprint InterfaceHash = Fingerprint::ZERO();
Fingerprint InterfaceHashIncludingTypeMembers = Fingerprint::ZERO();
llvm::sys::TimePoint<> LastModified = {};
uint64_t FileSize = 0;

BasicSourceFileInfo() {}
// Populate the from 'SF' member if exist. 'SF' will be cleared.
void populateWithSourceFileIfNeeded();

public:
BasicSourceFileInfo(StringRef FilePath,
Fingerprint InterfaceHashIncludingTypeMembers,
llvm::sys::TimePoint<> LastModified, uint64_t FileSize)
: FilePath(FilePath),
InterfaceHashIncludingTypeMembers(InterfaceHashIncludingTypeMembers),
LastModified(LastModified), FileSize(FileSize) {}

/// Construct with a 'SourceFile'. 'getInterfaceHashIncludingTypeMembers()',
/// 'getLastModified()' and 'getFileSize()' are laizily pupulated when
/// accessed.
BasicSourceFileInfo(const SourceFile *SF);

bool isFromSourceFile() const;

StringRef getFilePath() const { return FilePath; }

bool populate(const SourceFile *SF);
Fingerprint getInterfaceHashIncludingTypeMembers() const {
const_cast<BasicSourceFileInfo *>(this)->populateWithSourceFileIfNeeded();
return InterfaceHashIncludingTypeMembers;
}

llvm::sys::TimePoint<> getLastModified() const {
const_cast<BasicSourceFileInfo *>(this)->populateWithSourceFileIfNeeded();
return LastModified;
}

uint64_t getFileSize() const {
const_cast<BasicSourceFileInfo *>(this)->populateWithSourceFileIfNeeded();
return FileSize;
}
};

} // namespace swift
Expand Down
7 changes: 2 additions & 5 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1539,10 +1539,7 @@ void ModuleDecl::collectBasicSourceFileInfo(
llvm::function_ref<void(const BasicSourceFileInfo &)> callback) const {
for (const FileUnit *fileUnit : getFiles()) {
if (const auto *SF = dyn_cast<SourceFile>(fileUnit)) {
BasicSourceFileInfo info;
if (info.populate(SF))
continue;
callback(info);
callback(BasicSourceFileInfo(SF));
} else if (auto *serialized = dyn_cast<LoadedFile>(fileUnit)) {
serialized->collectBasicSourceFileInfo(callback);
}
Expand All @@ -1553,7 +1550,7 @@ Fingerprint ModuleDecl::getFingerprint() const {
StableHasher hasher = StableHasher::defaultHasher();
SmallVector<Fingerprint, 16> FPs;
collectBasicSourceFileInfo([&](const BasicSourceFileInfo &bsfi) {
FPs.emplace_back(bsfi.InterfaceHash);
FPs.emplace_back(bsfi.getInterfaceHashIncludingTypeMembers());
});

// Sort the fingerprints lexicographically so we have a stable hash despite
Expand Down
35 changes: 25 additions & 10 deletions lib/AST/RawComment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/PrimitiveParsing.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Markup/Markup.h"
Expand Down Expand Up @@ -247,26 +248,40 @@ CharSourceRange RawComment::getCharSourceRange() {
return CharSourceRange(Start, Length);
}

bool BasicSourceFileInfo::populate(const SourceFile *SF) {
BasicSourceFileInfo::BasicSourceFileInfo(const SourceFile *SF)
: SFAndIsFromSF(SF, true) {
FilePath = SF->getFilename();
}

bool BasicSourceFileInfo::isFromSourceFile() const {
return SFAndIsFromSF.getInt();
}

void BasicSourceFileInfo::populateWithSourceFileIfNeeded() {
const auto *SF = SFAndIsFromSF.getPointer();
if (!SF)
return;
SWIFT_DEFER {
SFAndIsFromSF.setPointer(nullptr);
};

SourceManager &SM = SF->getASTContext().SourceMgr;

auto filename = SF->getFilename();
if (filename.empty())
return true;
auto stat = SM.getFileSystem()->status(filename);
if (FilePath.empty())
return;
auto stat = SM.getFileSystem()->status(FilePath);
if (!stat)
return true;
return;

FilePath = filename;
LastModified = stat->getLastModificationTime();
FileSize = stat->getSize();

if (SF->hasInterfaceHash()) {
InterfaceHash = SF->getInterfaceHashIncludingTypeMembers();
InterfaceHashIncludingTypeMembers = SF->getInterfaceHashIncludingTypeMembers();
} else {
// FIXME: Parse the file with EnableInterfaceHash option.
InterfaceHash = Fingerprint::ZERO();
InterfaceHashIncludingTypeMembers = Fingerprint::ZERO();
}

return false;
return;
}
13 changes: 4 additions & 9 deletions lib/Serialization/ModuleFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -992,18 +992,13 @@ void ModuleFile::collectBasicSourceFileInfo(
size_t terminatorOffset = filePath.find('\0');
filePath = filePath.slice(0, terminatorOffset);

BasicSourceFileInfo info;
info.FilePath = filePath;
if (auto fingerprint = Fingerprint::fromString(fpStr))
info.InterfaceHash = fingerprint.getValue();
else {
auto fingerprint = Fingerprint::fromString(fpStr);
if (!fingerprint) {
llvm::errs() << "Unconvertable fingerprint '" << fpStr << "'\n";
abort();
}
info.LastModified =
llvm::sys::TimePoint<>(std::chrono::nanoseconds(timestamp));
info.FileSize = fileSize;
callback(info);

callback(BasicSourceFileInfo(filePath, fingerprint.getValue(), llvm::sys::TimePoint<>(std::chrono::nanoseconds(timestamp)), fileSize));
}
}

Expand Down
17 changes: 8 additions & 9 deletions lib/Serialization/SerializeDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,18 +794,20 @@ static void emitFileListRecord(llvm::BitstreamWriter &Out,
llvm::StringSet<> seenFilenames;

void emitSourceFileInfo(const BasicSourceFileInfo &info) {
if (info.getFilePath().empty())
return;
// Make 'FilePath' absolute for serialization;
SmallString<128> absolutePath = info.FilePath;
SmallString<128> absolutePath = info.getFilePath();
llvm::sys::fs::make_absolute(absolutePath);

// Don't emit duplicated files.
if (!seenFilenames.insert(info.FilePath).second)
if (!seenFilenames.insert(absolutePath).second)
return;

auto fileID = FWriter.getTextOffset(absolutePath);
auto fingerprintStr = info.InterfaceHash.getRawValue();
auto fingerprintStr = info.getInterfaceHashIncludingTypeMembers().getRawValue();
auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
info.LastModified.time_since_epoch())
info.getLastModified().time_since_epoch())
.count();

llvm::raw_svector_ostream out(Buffer);
Expand All @@ -818,7 +820,7 @@ static void emitFileListRecord(llvm::BitstreamWriter &Out,
// LastModified (nanoseconds since epoch).
writer.write<uint64_t>(timestamp);
// FileSize (num of bytes).
writer.write<uint64_t>(info.FileSize);
writer.write<uint64_t>(info.getFileSize());
}

SourceFileListWriter(StringWriter &FWriter) : FWriter(FWriter) {
Expand All @@ -827,10 +829,7 @@ static void emitFileListRecord(llvm::BitstreamWriter &Out,
} writer(FWriter);

if (SourceFile *SF = MSF.dyn_cast<SourceFile *>()) {
BasicSourceFileInfo info;
if (info.populate(SF))
return;
writer.emitSourceFileInfo(info);
writer.emitSourceFileInfo(BasicSourceFileInfo(SF));
} else {
auto *M = MSF.get<ModuleDecl *>();
M->collectBasicSourceFileInfo([&](const BasicSourceFileInfo &info) {
Expand Down
8 changes: 4 additions & 4 deletions tools/swift-ide-test/swift-ide-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2517,10 +2517,10 @@ static void printModuleMetadata(ModuleDecl *MD) {
<< ", force load: " << (lib.shouldForceLoad() ? "true" : "false") << "\n";
});
MD->collectBasicSourceFileInfo([&](const BasicSourceFileInfo &info) {
OS << "filepath=" << info.FilePath << "; ";
OS << "hash=" << info.InterfaceHash.getRawValue() << "; ";
OS << "mtime=" << info.LastModified << "; ";
OS << "size=" << info.FileSize;
OS << "filepath=" << info.getFilePath() << "; ";
OS << "hash=" << info.getInterfaceHashIncludingTypeMembers().getRawValue() << "; ";
OS << "mtime=" << info.getLastModified() << "; ";
OS << "size=" << info.getFileSize();
OS << "\n";
});
}
Expand Down