Move using below #include to make preamble happy
textDocument/references: if no references, first line or last line => list where this file is included
malloc_trim() only if files have been indexed in last cycle
Intern: use CachedHashStringRef
This commit is contained in:
Fangrui Song 2018-09-23 12:10:40 -07:00
parent 174466516e
commit 395e9d8724
22 changed files with 87 additions and 71 deletions

View File

@ -163,7 +163,9 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance(
CompletionSession &session, std::unique_ptr<CompilerInvocation> CI,
DiagnosticConsumer &DC, const WorkingFiles::Snapshot &snapshot,
std::vector<std::unique_ptr<llvm::MemoryBuffer>> &Bufs) {
std::string main = ResolveIfRelative(session.file.directory, CI->getFrontendOpts().Inputs[0].getFile());
std::string main = ResolveIfRelative(
session.file.directory,
sys::path::convert_to_slash(CI->getFrontendOpts().Inputs[0].getFile()));
for (auto &file : snapshot.files) {
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content));
if (file.filename == main)

View File

@ -10,7 +10,6 @@
#include "pipeline.hh"
#include "platform.h"
#include "serializer.h"
using namespace ccls;
#include <clang/AST/AST.h>
#include <clang/Frontend/FrontendAction.h>
@ -21,16 +20,15 @@ using namespace ccls;
#include <llvm/ADT/DenseSet.h>
#include <llvm/Support/CrashRecoveryContext.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/Timer.h>
using namespace clang;
using llvm::Timer;
#include <algorithm>
#include <inttypes.h>
#include <limits.h>
#include <map>
#include <unordered_set>
using namespace ccls;
using namespace clang;
namespace {
constexpr int kInitializerMaxLines = 3;
@ -494,7 +492,7 @@ public:
def.short_name_offset = Str.size() + qualified.size() - short_name.size();
def.short_name_size = short_name.size();
Str += StringRef(qualified.data(), qualified.size());
def.detailed_name = Intern(Str.str());
def.detailed_name = Intern(Str);
} else {
SetName(D, short_name, qualified, def);
}

View File

@ -18,7 +18,6 @@
#include <llvm/ADT/DenseMap.h>
#include <algorithm>
#include <optional>
#include <stdint.h>
#include <string_view>
#include <unordered_map>

View File

@ -8,15 +8,12 @@
#include "serializers/json.h"
#include "test.h"
#include "working_files.h"
using namespace ccls;
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/CrashRecoveryContext.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/Program.h>
#include <llvm/Support/Signals.h>
using namespace llvm;
using namespace llvm::cl;
#include <rapidjson/error/en.h>
@ -26,6 +23,10 @@ using namespace llvm::cl;
#include <unordered_map>
#include <vector>
using namespace ccls;
using namespace llvm;
using namespace llvm::cl;
std::string g_init_options;
namespace {

View File

@ -75,7 +75,6 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting, jsonrpc, method,
struct MessageHandler {
DB *db = nullptr;
MultiQueueWaiter *waiter = nullptr;
Project *project = nullptr;
VFS *vfs = nullptr;
SemanticHighlight *highlight = nullptr;

View File

@ -5,10 +5,11 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
#include <unordered_set>
using namespace ccls;
namespace {
MethodType kMethodType = "$ccls/call";

View File

@ -5,14 +5,15 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
#include <clang/AST/Type.h>
#include <llvm/ADT/DenseSet.h>
using namespace clang;
#include <unordered_set>
using namespace ccls;
using namespace clang;
namespace {
MethodType kMethodType = "$ccls/member";

View File

@ -5,14 +5,14 @@
#include "match.h"
#include "message_handler.h"
#include "pipeline.hh"
#include "platform.h"
#include "project.h"
#include "working_files.h"
using namespace ccls;
#include <queue>
#include <unordered_set>
using namespace ccls;
namespace {
MethodType kMethodType = "$ccls/reload";
@ -22,8 +22,7 @@ struct In_CclsReload : public NotificationInMessage {
bool dependencies = true;
std::vector<std::string> whitelist;
std::vector<std::string> blacklist;
};
Params params;
} params;
};
MAKE_REFLECT_STRUCT(In_CclsReload::Params, dependencies, whitelist,
blacklist);

View File

@ -11,16 +11,16 @@
#include "project.h"
#include "serializers/json.h"
#include "working_files.h"
using namespace ccls;
#include <llvm/ADT/Twine.h>
#include <llvm/Support/Threading.h>
using namespace llvm;
#include <iostream>
#include <stdexcept>
#include <thread>
using namespace ccls;
using namespace llvm;
// TODO Cleanup global variables
extern std::string g_init_options;

View File

@ -8,16 +8,16 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "working_files.h"
using namespace ccls;
#include <clang/Sema/CodeCompleteConsumer.h>
#include <clang/Sema/Sema.h>
#include <llvm/Support/Timer.h>
using namespace clang;
using namespace llvm;
#include <regex>
using namespace ccls;
using namespace clang;
using namespace llvm;
namespace {
MethodType kMethodType = "textDocument/completion";
@ -167,10 +167,6 @@ void FilterAndSortCompletionResponse(
const std::string &complete_text, bool has_open_paren) {
if (!g_config->completion.filterAndSort)
return;
static Timer timer("FilterAndSortCompletionResponse", "");
TimeRegion region(timer);
auto &items = complete_response->result.items;
auto finalize = [&]() {

View File

@ -4,11 +4,12 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
#include <cstdlib>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
using namespace ccls;
namespace {
MethodType kMethodType = "textDocument/definition";

View File

@ -14,8 +14,7 @@ struct In_TextDocumentDidClose : public NotificationInMessage {
MethodType GetMethodType() const override { return kMethodType; }
struct Params {
lsTextDocumentIdentifier textDocument;
};
Params params;
} params;
};
MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument);
MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params);

View File

@ -12,7 +12,6 @@ using namespace ccls;
namespace {
MethodType kMethodType = "textDocument/didOpen";
// Open, view, change, close file
struct In_TextDocumentDidOpen : public NotificationInMessage {
MethodType GetMethodType() const override { return kMethodType; }
@ -37,7 +36,7 @@ struct Handler_TextDocumentDidOpen
// NOTE: This function blocks code lens. If it starts taking a long time
// we will need to find a way to unblock the code lens request.
const auto &params = request->params;
std::string path = params.textDocument.uri.GetPath();
const std::string &path = params.textDocument.uri.GetPath();
WorkingFile *working_file = working_files->OnOpen(params.textDocument);
if (std::optional<std::string> cached_file_contents =

View File

@ -4,7 +4,6 @@
#include "clang_complete.hh"
#include "message_handler.h"
#include "pipeline.hh"
#include "project.h"
using namespace ccls;
namespace {
@ -32,7 +31,7 @@ struct Handler_TextDocumentDidSave
void Run(In_TextDocumentDidSave *request) override {
const auto &params = request->params;
std::string path = params.textDocument.uri.GetPath();
const std::string &path = params.textDocument.uri.GetPath();
pipeline::Index(path, {}, IndexMode::Normal);
clang_complete->NotifySave(path);
}

View File

@ -4,10 +4,11 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
#include <unordered_set>
using namespace ccls;
namespace {
MethodType kMethodType = "textDocument/references";
@ -54,13 +55,17 @@ struct Handler_TextDocumentReferences
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
Out_TextDocumentReferences out;
out.id = request->id;
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
if (!file) {
pipeline::WriteStdout(kMethodType, out);
return;
}
bool container = g_config->xref.container;
std::unordered_set<Use> seen_uses;
int line = params.position.line;
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position)) {
// Found symbol. Return references.
@ -115,7 +120,7 @@ struct Handler_TextDocumentReferences
// = 0,
// use the current filename.
std::string path;
if (params.position.line == 0)
if (line == 0 || line >= (int)wfile->buffer_lines.size() - 1)
path = file->def->path;
for (const IndexInclude &include : file->def->includes)
if (include.line == params.position.line) {

View File

@ -4,12 +4,11 @@
#include "clang_complete.hh"
#include "message_handler.h"
#include "pipeline.hh"
using namespace ccls;
#include <clang/Sema/Sema.h>
using namespace clang;
#include <stdint.h>
using namespace ccls;
using namespace clang;
namespace {
MethodType kMethodType = "textDocument/signatureHelp";

View File

@ -5,13 +5,14 @@
#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;
#include <algorithm>
#include <ctype.h>
#include <functional>
#include <limits.h>
using namespace ccls;
namespace {
MethodType kMethodType = "workspace/symbol";

View File

@ -478,7 +478,6 @@ void MainLoop() {
// Setup shared references.
for (MessageHandler *handler : *MessageHandler::message_handlers) {
handler->db = &db;
handler->waiter = indexer_waiter;
handler->project = &project;
handler->vfs = &vfs;
handler->highlight = &highlight;
@ -487,6 +486,7 @@ void MainLoop() {
handler->include_complete = &include_complete;
}
bool last_indexed = false;
while (true) {
std::vector<std::unique_ptr<InMessage>> messages = on_request->DequeueAll();
bool did_work = messages.size();
@ -503,18 +503,22 @@ void MainLoop() {
LOG_S(ERROR) << "No handler for " << message->GetMethodType();
}
for (int i = 80; i--;) {
bool indexed = false;
for (int i = 20; i--;) {
std::optional<IndexUpdate> update = on_indexed->TryPopFront();
if (!update)
break;
did_work = true;
indexed = true;
Main_OnIndexed(&db, &highlight, &working_files, &*update);
}
if (!did_work) {
if (last_indexed)
FreeUnusedMemory();
main_waiter->Wait(on_indexed, on_request);
}
last_indexed = indexed;
}
}

View File

@ -101,7 +101,7 @@ std::string NormalizePath(const std::string &path) {
void FreeUnusedMemory() {
#ifdef __GLIBC__
malloc_trim(0);
malloc_trim(4 * 1024 * 1024);
#endif
}

View File

@ -13,18 +13,14 @@
#include "serializers/json.h"
#include "utils.h"
#include "working_files.h"
using namespace ccls;
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Tooling/CompilationDatabase.h>
#include <llvm/ADT/ArrayRef.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/Support/LineIterator.h>
using namespace clang;
using namespace llvm;
#include <rapidjson/writer.h>
@ -32,10 +28,14 @@ using namespace llvm;
#include <unistd.h>
#endif
#include <limits>
#include <limits.h>
#include <unordered_set>
#include <vector>
using namespace ccls;
using namespace clang;
using namespace llvm;
namespace {
enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand };
@ -387,7 +387,7 @@ Project::FindCompilationEntryForFile(const std::string &filename) {
// We couldn't find the file. Try to infer it.
// TODO: Cache inferred file in a separate array (using a lock or similar)
Entry *best_entry = nullptr;
int best_score = std::numeric_limits<int>::min();
int best_score = INT_MIN;
for (Entry &entry : entries) {
int score = ComputeGuessScore(filename, entry.filename);
if (score > best_score) {

View File

@ -154,12 +154,11 @@ void Reflect(Reader &vis, DenseMap<CachedHashStringRef, int64_t> &v) {
if (vis.Format() == SerializeFormat::Json) {
auto &vis1 = static_cast<JsonReader&>(vis);
for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it)
v[CachedHashStringRef(Intern(it->name.GetString()))] =
it->value.GetInt64();
v[InternH(it->name.GetString())] = it->value.GetInt64();
} else {
vis.IterArray([&](Reader &entry) {
Reflect(entry, name);
Reflect(entry, v[CachedHashStringRef(Intern(name))]);
Reflect(entry, v[InternH(name)]);
});
}
}
@ -344,18 +343,26 @@ void Reflect(Writer &visitor, SerializeFormat &value) {
namespace ccls {
static BumpPtrAllocator Alloc;
static DenseSet<StringRef> Strings;
static DenseSet<CachedHashStringRef> Strings;
static std::mutex AllocMutex;
const char *Intern(const std::string &str) {
if (str.empty())
return "";
StringRef Str(str.data(), str.size() + 1);
CachedHashStringRef InternH(StringRef S) {
if (S.empty())
S = "";
CachedHashString HS(S);
std::lock_guard lock(AllocMutex);
auto R = Strings.insert(Str);
if (R.second)
*R.first = Str.copy(Alloc);
return R.first->data();
auto R = Strings.insert(HS);
if (R.second) {
char *P = Alloc.Allocate<char>(S.size() + 1);
memcpy(P, S.data(), S.size());
P[S.size()] = '\0';
*R.first = CachedHashStringRef(StringRef(P, S.size()), HS.hash());
}
return *R.first;
}
const char *Intern(StringRef S) {
return InternH(S).val().data();
}
std::string Serialize(SerializeFormat format, IndexFile &file) {
@ -470,7 +477,7 @@ Deserialize(SerializeFormat format, const std::string &path,
for (auto &it : file->dependencies) {
std::string path = it.first.val().str();
DoPathMapping(path);
dependencies[CachedHashStringRef(Intern(path))] = it.second;
dependencies[InternH(path)] = it.second;
}
file->dependencies = std::move(dependencies);
}

View File

@ -18,6 +18,11 @@
#include <type_traits>
#include <vector>
namespace llvm {
class CachedHashStringRef;
class StringRef;
}
enum class SerializeFormat { Binary, Json };
struct JsonNull {};
@ -308,7 +313,8 @@ template <typename T> void ReflectMember(Writer &vis, const char *name, T &v) {
// API
namespace ccls {
const char *Intern(const std::string &str);
const char *Intern(llvm::StringRef str);
llvm::CachedHashStringRef InternH(llvm::StringRef str);
std::string Serialize(SerializeFormat format, IndexFile &file);
std::unique_ptr<IndexFile>
Deserialize(SerializeFormat format, const std::string &path,