Skip to content

Commit

Permalink
Add initialization option index.initialNoLinkage: false
Browse files Browse the repository at this point in the history
By default, the background indexer doesn't handle names of no linkage.
They are indexed when their files are opened. This saves memory and
makes cache files smaller.
  • Loading branch information
MaskRay committed Mar 25, 2019
1 parent b6155dd commit 17eaca8
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 44 deletions.
18 changes: 11 additions & 7 deletions src/config.hh
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,12 @@ struct Config {
// - https://github.com/autozimu/LanguageClient-neovim/issues/224
int comments = 2;

// By default, all project entries will be indexed on initialization. Use
// these two options to exclude some. They can still be indexed after you
// open them.
// If false, names of no linkage are not indexed in the background. They are
// indexed after the files are opened.
bool initialNoLinkage = false;

// Use the two options to exclude files that should not be indexed in the
// background.
std::vector<std::string> initialBlacklist;
std::vector<std::string> initialWhitelist;

Expand Down Expand Up @@ -332,10 +335,11 @@ REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave,
spellChecking, whitelist)
REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, whitelist)
REFLECT_STRUCT(Config::Index::Name, suppressUnwrittenScope);
REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist,
initialWhitelist, maxInitializerLines, multiVersion,
multiVersionBlacklist, multiVersionWhitelist, name, onChange,
parametersInDeclarations, threads, trackDependency, whitelist);
REFLECT_STRUCT(Config::Index, blacklist, comments, initialNoLinkage,
initialBlacklist, initialWhitelist, maxInitializerLines,
multiVersion, multiVersionBlacklist, multiVersionWhitelist, name,
onChange, parametersInDeclarations, threads, trackDependency,
whitelist);
REFLECT_STRUCT(Config::Request, timeout);
REFLECT_STRUCT(Config::Session, maxNum);
REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort);
Expand Down
38 changes: 25 additions & 13 deletions src/indexer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ struct IndexParam {

VFS &vfs;
ASTContext *Ctx;
IndexParam(VFS &vfs) : vfs(vfs) {}
bool no_linkage;
IndexParam(VFS &vfs, bool no_linkage) : vfs(vfs), no_linkage(no_linkage) {}

void SeenFile(const FileEntry &File) {
// If this is the first time we have seen the file (ignoring if we are
Expand All @@ -66,9 +67,10 @@ struct IndexParam {
if (std::optional<std::string> content = ReadContent(path))
it->second.content = *content;

if (!vfs.Stamp(path, it->second.mtime, 1))
if (!vfs.Stamp(path, it->second.mtime, no_linkage ? 3 : 1))
return;
it->second.db = std::make_unique<IndexFile>(path, it->second.content);
it->second.db =
std::make_unique<IndexFile>(path, it->second.content, no_linkage);
}
}

Expand Down Expand Up @@ -679,6 +681,12 @@ class IndexDataConsumer : public index::IndexDataConsumer {
bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
ArrayRef<index::SymbolRelation> Relations,
SourceLocation Loc, ASTNodeInfo ASTNode) override {
if (!param.no_linkage) {
if (auto *ND = dyn_cast<NamedDecl>(D); ND && ND->hasLinkage())
;
else
return true;
}
SourceManager &SM = Ctx->getSourceManager();
const LangOptions &Lang = Ctx->getLangOpts();
FileID LocFID;
Expand Down Expand Up @@ -1153,11 +1161,12 @@ class IndexFrontendAction : public ASTFrontendAction {
};
} // namespace

const int IndexFile::kMajorVersion = 20;
const int IndexFile::kMajorVersion = 21;
const int IndexFile::kMinorVersion = 0;

IndexFile::IndexFile(const std::string &path, const std::string &contents)
: path(path), file_contents(contents) {}
IndexFile::IndexFile(const std::string &path, const std::string &contents,
bool no_linkage)
: path(path), no_linkage(no_linkage), file_contents(contents) {}

IndexFunc &IndexFile::ToFunc(Usr usr) {
auto [it, inserted] = usr2func.try_emplace(usr);
Expand Down Expand Up @@ -1204,7 +1213,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
const std::string &opt_wdir, const std::string &main,
const std::vector<const char *> &args,
const std::vector<std::pair<std::string, std::string>> &remapped,
bool &ok) {
bool no_linkage, bool &ok) {
ok = true;
auto PCH = std::make_shared<PCHContainerOperations>();
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getRealFileSystem();
Expand Down Expand Up @@ -1237,19 +1246,22 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
if (!Clang->hasTarget())
return {};

IndexParam param(*vfs);
IndexParam param(*vfs, no_linkage);
auto DataConsumer = std::make_shared<IndexDataConsumer>(param);

index::IndexingOptions IndexOpts;
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::All;
IndexOpts.IndexFunctionLocals = true;
IndexOpts.IndexImplicitInstantiation = true;
if (no_linkage) {
IndexOpts.IndexFunctionLocals = true;
IndexOpts.IndexImplicitInstantiation = true;
#if LLVM_VERSION_MAJOR >= 9
IndexOpts.IndexParametersInDeclarations =
g_config->index.parametersInDeclarations;
IndexOpts.IndexTemplateParameters = true;

IndexOpts.IndexParametersInDeclarations =
g_config->index.parametersInDeclarations;
IndexOpts.IndexTemplateParameters = true;
#endif
}

std::unique_ptr<FrontendAction> Action = createIndexingAction(
DataConsumer, IndexOpts, std::make_unique<IndexFrontendAction>(param));
Expand Down
6 changes: 4 additions & 2 deletions src/indexer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ struct IndexFile {
// This is unfortunately time_t as used by clang::FileEntry
int64_t mtime = 0;
LanguageId language = LanguageId::C;
bool no_linkage;

// uid2lid_and_path is used to generate lid2path, but not serialized.
std::unordered_map<llvm::sys::fs::UniqueID, std::pair<int, std::string>>
Expand All @@ -316,7 +317,8 @@ struct IndexFile {
// File contents at the time of index. Not serialized.
std::string file_contents;

IndexFile(const std::string &path, const std::string &contents);
IndexFile(const std::string &path, const std::string &contents,
bool no_linkage);

IndexFunc &ToFunc(Usr usr);
IndexType &ToType(Usr usr);
Expand All @@ -336,7 +338,7 @@ Index(SemaManager *complete, WorkingFiles *wfiles, VFS *vfs,
const std::string &opt_wdir, const std::string &file,
const std::vector<const char *> &args,
const std::vector<std::pair<std::string, std::string>> &remapped,
bool &ok);
bool all_linkages, bool &ok);
} // namespace idx
} // namespace ccls

Expand Down
2 changes: 1 addition & 1 deletion src/messages/workspace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void MessageHandler::workspace_didChangeWatchedFiles(
return;

IndexMode mode =
wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::NonInteractive;
wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::Background;
switch (event.type) {
case FileChangeType::Created:
case FileChangeType::Changed: {
Expand Down
34 changes: 21 additions & 13 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,20 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
std::string path_to_index = entry.filename;
std::unique_ptr<IndexFile> prev;

bool deleted = false;
bool deleted = false, no_linkage = g_config->index.initialNoLinkage ||
request.mode != IndexMode::Background;
int reparse = 0;
std::optional<int64_t> write_time = LastWriteTime(path_to_index);
if (!write_time) {
deleted = true;
} else {
reparse = vfs->Stamp(path_to_index, *write_time, 0);
if (vfs->Stamp(path_to_index, *write_time, no_linkage ? 2 : 0))
reparse = 1;
if (request.path != path_to_index) {
std::optional<int64_t> mtime1 = LastWriteTime(request.path);
if (!mtime1)
deleted = true;
else if (vfs->Stamp(request.path, *mtime1, 0))
else if (vfs->Stamp(request.path, *mtime1, no_linkage ? 2 : 0))
reparse = 2;
}
}
Expand All @@ -250,8 +252,9 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
do {
std::unique_lock lock(GetFileMutex(path_to_index));
prev = RawCacheLoad(path_to_index);
if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args,
std::nullopt))
if (!prev || prev->no_linkage < no_linkage ||
CacheInvalid(vfs, prev.get(), path_to_index, entry.args,
std::nullopt))
break;
if (track)
for (const auto &dep : prev->dependencies) {
Expand Down Expand Up @@ -280,10 +283,13 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
auto dependencies = prev->dependencies;
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
on_indexed->PushBack(std::move(update),
request.mode != IndexMode::NonInteractive);
request.mode != IndexMode::Background);
{
std::lock_guard lock1(vfs->mutex);
vfs->state[path_to_index].loaded++;
VFS::State &st = vfs->state[path_to_index];
st.loaded++;
if (prev->no_linkage)
st.step = 2;
}
lock.unlock();

Expand All @@ -302,10 +308,12 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
continue;
st.loaded++;
st.timestamp = prev->mtime;
if (prev->no_linkage)
st.step = 3;
}
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
on_indexed->PushBack(std::move(update),
request.mode != IndexMode::NonInteractive);
request.mode != IndexMode::Background);
if (entry.id >= 0) {
std::lock_guard lock2(project->mtx);
project->root2folder[entry.root].path2entry_index[path] = entry.id;
Expand All @@ -326,9 +334,9 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,

std::vector<std::unique_ptr<IndexFile>> indexes;
if (deleted) {
indexes.push_back(std::make_unique<IndexFile>(request.path, ""));
indexes.push_back(std::make_unique<IndexFile>(request.path, "", false));
if (request.path != path_to_index)
indexes.push_back(std::make_unique<IndexFile>(path_to_index, ""));
indexes.push_back(std::make_unique<IndexFile>(path_to_index, "", false));
} else {
std::vector<std::pair<std::string, std::string>> remapped;
if (g_config->index.onChange) {
Expand All @@ -338,7 +346,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
}
bool ok;
indexes = idx::Index(completion, wfiles, vfs, entry.directory,
path_to_index, entry.args, remapped, ok);
path_to_index, entry.args, remapped, no_linkage, ok);

if (!ok) {
if (request.id.Valid()) {
Expand Down Expand Up @@ -390,7 +398,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
}
}
on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()),
request.mode != IndexMode::NonInteractive);
request.mode != IndexMode::Background);
{
std::lock_guard lock1(vfs->mutex);
vfs->state[path].loaded++;
Expand Down Expand Up @@ -730,7 +738,7 @@ void Index(const std::string &path, const std::vector<const char *> &args,
IndexMode mode, bool must_exist, RequestId id) {
pending_index_requests++;
index_request->PushBack({path, args, mode, must_exist, id},
mode != IndexMode::NonInteractive);
mode != IndexMode::Background);
}

void RemoveCache(const std::string &path) {
Expand Down
2 changes: 1 addition & 1 deletion src/pipeline.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct VFS {
};

enum class IndexMode {
NonInteractive,
Background,
OnChange,
Normal,
};
Expand Down
6 changes: 3 additions & 3 deletions src/project.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
bool interactive = wfiles->GetFile(entry.filename) != nullptr;
pipeline::Index(entry.filename, entry.args,
interactive ? IndexMode::Normal
: IndexMode::NonInteractive,
: IndexMode::Background,
false, id);
} else {
LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason
Expand All @@ -578,7 +578,7 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
pipeline::loaded_ts = pipeline::tick;
// Dummy request to indicate that project is loaded and
// trigger refreshing semantic highlight for all working files.
pipeline::Index("", {}, IndexMode::NonInteractive, false);
pipeline::Index("", {}, IndexMode::Background, false);
}

void Project::IndexRelated(const std::string &path) {
Expand All @@ -592,7 +592,7 @@ void Project::IndexRelated(const std::string &path) {
std::string reason;
if (sys::path::stem(entry.filename) == stem && entry.filename != path &&
match.Matches(entry.filename, &reason))
pipeline::Index(entry.filename, entry.args, IndexMode::NonInteractive,
pipeline::Index(entry.filename, entry.args, IndexMode::Background,
true);
}
break;
Expand Down
2 changes: 1 addition & 1 deletion src/query.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ QueryType::Def Convert(const IndexType::Def &o) {

IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
IndexUpdate r;
static IndexFile empty(current->path, "<empty>");
static IndexFile empty(current->path, "<empty>", false);
if (previous)
r.prev_lid2path = std::move(previous->lid2path);
else
Expand Down
5 changes: 3 additions & 2 deletions src/serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ template <typename TVisitor> void Reflect1(TVisitor &vis, IndexFile &v) {
if (!gTestOutputMode) {
REFLECT_MEMBER(mtime);
REFLECT_MEMBER(language);
REFLECT_MEMBER(no_linkage);
REFLECT_MEMBER(lid2path);
REFLECT_MEMBER(import_file);
REFLECT_MEMBER(args);
Expand Down Expand Up @@ -470,7 +471,7 @@ Deserialize(SerializeFormat format, const std::string &path,
if (major != IndexFile::kMajorVersion ||
minor != IndexFile::kMinorVersion)
throw std::invalid_argument("Invalid version");
file = std::make_unique<IndexFile>(path, file_content);
file = std::make_unique<IndexFile>(path, file_content, false);
ReflectFile(reader, *file);
} catch (std::invalid_argument &e) {
LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what();
Expand All @@ -493,7 +494,7 @@ Deserialize(SerializeFormat format, const std::string &path,
if (reader.HasParseError())
return nullptr;

file = std::make_unique<IndexFile>(path, file_content);
file = std::make_unique<IndexFile>(path, file_content, false);
JsonReader json_reader{&reader};
try {
ReflectFile(json_reader, *file);
Expand Down
3 changes: 2 additions & 1 deletion src/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) {
for (auto &arg : flags)
cargs.push_back(arg.c_str());
bool ok;
auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}, ok);
auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs,
{}, true, ok);

for (const auto &entry : all_expected_output) {
const std::string &expected_path = entry.first;
Expand Down

0 comments on commit 17eaca8

Please sign in to comment.