mirror of
https://github.com/MaskRay/ccls.git
synced 2024-12-01 20:07:08 +00:00
Change containers of Query*::Def fields from std::vector to ccls::Vec
Query*::Def contain several immutable std::vector fields. Change them to ccls::Vec to save bytes which were wasted by `capacity`.
This commit is contained in:
parent
89ec8ed236
commit
4d68101d0a
@ -131,6 +131,9 @@ void Reflect(BinaryWriter &visitor, SymbolRef &value);
|
||||
void Reflect(BinaryWriter &visitor, Use &value);
|
||||
void Reflect(BinaryWriter &visitor, DeclRef &value);
|
||||
|
||||
template <typename T>
|
||||
using VectorAdapter = std::vector<T, std::allocator<T>>;
|
||||
|
||||
template <typename D> struct NameMixin {
|
||||
std::string_view Name(bool qualified) const {
|
||||
auto self = static_cast<const D *>(this);
|
||||
@ -144,7 +147,8 @@ template <typename D> struct NameMixin {
|
||||
}
|
||||
};
|
||||
|
||||
struct FuncDef : NameMixin<FuncDef> {
|
||||
template <template <typename T> class V>
|
||||
struct FuncDef : NameMixin<FuncDef<V>> {
|
||||
// General metadata.
|
||||
const char *detailed_name = "";
|
||||
const char *hover = "";
|
||||
@ -152,11 +156,11 @@ struct FuncDef : NameMixin<FuncDef> {
|
||||
Maybe<DeclRef> spell;
|
||||
|
||||
// Method this method overrides.
|
||||
std::vector<Usr> bases;
|
||||
V<Usr> bases;
|
||||
// Local variables or parameters.
|
||||
std::vector<Usr> vars;
|
||||
V<Usr> vars;
|
||||
// Functions that this function calls.
|
||||
std::vector<SymbolRef> callees;
|
||||
V<SymbolRef> callees;
|
||||
|
||||
int file_id = -1; // not serialized
|
||||
int16_t qual_name_offset = 0;
|
||||
@ -166,14 +170,15 @@ struct FuncDef : NameMixin<FuncDef> {
|
||||
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||
uint8_t storage = clang::SC_None;
|
||||
|
||||
std::vector<Usr> GetBases() const { return bases; }
|
||||
const Usr *bases_begin() const { return bases.begin(); }
|
||||
const Usr *bases_end() const { return bases.end(); }
|
||||
};
|
||||
REFLECT_STRUCT(FuncDef, detailed_name, hover, comments, spell, bases, vars,
|
||||
callees, qual_name_offset, short_name_offset,
|
||||
REFLECT_STRUCT(FuncDef<VectorAdapter>, detailed_name, hover, comments, spell,
|
||||
bases, vars, callees, qual_name_offset, short_name_offset,
|
||||
short_name_size, kind, parent_kind, storage);
|
||||
|
||||
struct IndexFunc : NameMixin<IndexFunc> {
|
||||
using Def = FuncDef;
|
||||
using Def = FuncDef<VectorAdapter>;
|
||||
Usr usr;
|
||||
Def def;
|
||||
std::vector<DeclRef> declarations;
|
||||
@ -181,17 +186,18 @@ struct IndexFunc : NameMixin<IndexFunc> {
|
||||
std::vector<Use> uses;
|
||||
};
|
||||
|
||||
struct TypeDef : NameMixin<TypeDef> {
|
||||
template <template <typename T> class V>
|
||||
struct TypeDef : NameMixin<TypeDef<V>> {
|
||||
const char *detailed_name = "";
|
||||
const char *hover = "";
|
||||
const char *comments = "";
|
||||
Maybe<DeclRef> spell;
|
||||
|
||||
std::vector<Usr> bases;
|
||||
V<Usr> bases;
|
||||
// Types, functions, and variables defined in this type.
|
||||
std::vector<Usr> funcs;
|
||||
std::vector<Usr> types;
|
||||
std::vector<std::pair<Usr, int64_t>> vars;
|
||||
V<Usr> funcs;
|
||||
V<Usr> types;
|
||||
V<std::pair<Usr, int64_t>> vars;
|
||||
|
||||
// If set, then this is the same underlying type as the given value (ie, this
|
||||
// type comes from a using or typedef statement).
|
||||
@ -203,14 +209,15 @@ struct TypeDef : NameMixin<TypeDef> {
|
||||
SymbolKind kind = SymbolKind::Unknown;
|
||||
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||
|
||||
std::vector<Usr> GetBases() const { return bases; }
|
||||
const Usr *bases_begin() const { return bases.begin(); }
|
||||
const Usr *bases_end() const { return bases.end(); }
|
||||
};
|
||||
REFLECT_STRUCT(TypeDef, detailed_name, hover, comments, spell, bases,
|
||||
funcs, types, vars, alias_of, qual_name_offset,
|
||||
REFLECT_STRUCT(TypeDef<VectorAdapter>, detailed_name, hover, comments, spell,
|
||||
bases, funcs, types, vars, alias_of, qual_name_offset,
|
||||
short_name_offset, short_name_size, kind, parent_kind);
|
||||
|
||||
struct IndexType {
|
||||
using Def = TypeDef;
|
||||
using Def = TypeDef<VectorAdapter>;
|
||||
Usr usr;
|
||||
Def def;
|
||||
std::vector<DeclRef> declarations;
|
||||
@ -248,7 +255,8 @@ struct VarDef : NameMixin<VarDef> {
|
||||
storage == clang::SC_Register);
|
||||
}
|
||||
|
||||
std::vector<Usr> GetBases() const { return {}; }
|
||||
const Usr *bases_begin() const { return nullptr; }
|
||||
const Usr *bases_end() const { return nullptr; }
|
||||
};
|
||||
REFLECT_STRUCT(VarDef, detailed_name, hover, comments, spell, type,
|
||||
qual_name_offset, short_name_offset, short_name_size, kind,
|
||||
|
@ -4,8 +4,12 @@
|
||||
#include "message_handler.hh"
|
||||
#include "query.hh"
|
||||
|
||||
#include <llvm/ADT/iterator_range.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace ccls {
|
||||
namespace {
|
||||
struct ReferenceParam : public TextDocumentPositionParam {
|
||||
@ -68,7 +72,7 @@ void MessageHandler::textDocument_references(JsonReader &reader,
|
||||
if (def.spell) {
|
||||
parent_kind = GetSymbolKind(db, sym);
|
||||
if (param.base)
|
||||
for (Usr usr : def.GetBases())
|
||||
for (Usr usr : make_range(def.bases_begin(), def.bases_end()))
|
||||
if (!seen.count(usr)) {
|
||||
seen.insert(usr);
|
||||
stack.push_back(usr);
|
||||
|
72
src/query.cc
72
src/query.cc
@ -69,6 +69,51 @@ bool TryReplaceDef(llvm::SmallVectorImpl<Q> &def_list, Q &&def) {
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename T> Vec<T> Convert(const std::vector<T> &o) {
|
||||
Vec<T> r{std::make_unique<T[]>(o.size()), (int)o.size()};
|
||||
std::copy(o.begin(), o.end(), r.begin());
|
||||
return r;
|
||||
}
|
||||
|
||||
QueryFunc::Def Convert(const IndexFunc::Def &o) {
|
||||
QueryFunc::Def r;
|
||||
r.detailed_name = o.detailed_name;
|
||||
r.hover = o.hover;
|
||||
r.comments = o.comments;
|
||||
r.spell = o.spell;
|
||||
r.bases = Convert(o.bases);
|
||||
r.vars = Convert(o.vars);
|
||||
r.callees = Convert(o.callees);
|
||||
// no file_id
|
||||
r.qual_name_offset = o.qual_name_offset;
|
||||
r.short_name_offset = o.short_name_offset;
|
||||
r.short_name_size = o.short_name_size;
|
||||
r.kind = o.kind;
|
||||
r.parent_kind = o.parent_kind;
|
||||
r.storage = o.storage;
|
||||
return r;
|
||||
}
|
||||
|
||||
QueryType::Def Convert(const IndexType::Def &o) {
|
||||
QueryType::Def r;
|
||||
r.detailed_name = o.detailed_name;
|
||||
r.hover = o.hover;
|
||||
r.comments = o.comments;
|
||||
r.spell = o.spell;
|
||||
r.bases = Convert(o.bases);
|
||||
r.funcs = Convert(o.funcs);
|
||||
r.types = Convert(o.types);
|
||||
r.vars = Convert(o.vars);
|
||||
r.alias_of = o.alias_of;
|
||||
// no file_id
|
||||
r.qual_name_offset = o.qual_name_offset;
|
||||
r.short_name_offset = o.short_name_offset;
|
||||
r.short_name_size = o.short_name_size;
|
||||
r.kind = o.kind;
|
||||
r.parent_kind = o.parent_kind;
|
||||
return r;
|
||||
}
|
||||
|
||||
IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
|
||||
IndexUpdate r;
|
||||
static IndexFile empty(current->path, "<empty>");
|
||||
@ -82,7 +127,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
|
||||
for (auto &it : previous->usr2func) {
|
||||
auto &func = it.second;
|
||||
if (func.def.detailed_name[0])
|
||||
r.funcs_removed.emplace_back(func.usr, func.def);
|
||||
r.funcs_removed.emplace_back(func.usr, Convert(func.def));
|
||||
r.funcs_declarations[func.usr].first = std::move(func.declarations);
|
||||
r.funcs_uses[func.usr].first = std::move(func.uses);
|
||||
r.funcs_derived[func.usr].first = std::move(func.derived);
|
||||
@ -90,7 +135,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
|
||||
for (auto &it : current->usr2func) {
|
||||
auto &func = it.second;
|
||||
if (func.def.detailed_name[0])
|
||||
r.funcs_def_update.emplace_back(it.first, func.def);
|
||||
r.funcs_def_update.emplace_back(it.first, Convert(func.def));
|
||||
r.funcs_declarations[func.usr].second = std::move(func.declarations);
|
||||
r.funcs_uses[func.usr].second = std::move(func.uses);
|
||||
r.funcs_derived[func.usr].second = std::move(func.derived);
|
||||
@ -100,7 +145,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
|
||||
for (auto &it : previous->usr2type) {
|
||||
auto &type = it.second;
|
||||
if (type.def.detailed_name[0])
|
||||
r.types_removed.emplace_back(type.usr, type.def);
|
||||
r.types_removed.emplace_back(type.usr, Convert(type.def));
|
||||
r.types_declarations[type.usr].first = std::move(type.declarations);
|
||||
r.types_uses[type.usr].first = std::move(type.uses);
|
||||
r.types_derived[type.usr].first = std::move(type.derived);
|
||||
@ -109,7 +154,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) {
|
||||
for (auto &it : current->usr2type) {
|
||||
auto &type = it.second;
|
||||
if (type.def.detailed_name[0])
|
||||
r.types_def_update.emplace_back(it.first, type.def);
|
||||
r.types_def_update.emplace_back(it.first, Convert(type.def));
|
||||
r.types_declarations[type.usr].second = std::move(type.declarations);
|
||||
r.types_uses[type.usr].second = std::move(type.uses);
|
||||
r.types_derived[type.usr].second = std::move(type.derived);
|
||||
@ -202,8 +247,10 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
||||
#define REMOVE_ADD(C, F) \
|
||||
for (auto &it : u->C##s_##F) { \
|
||||
auto R = C##_usr.try_emplace({it.first}, C##_usr.size()); \
|
||||
if (R.second) \
|
||||
C##s.emplace_back().usr = it.first; \
|
||||
if (R.second) { \
|
||||
C##s.emplace_back(); \
|
||||
C##s.back().usr = it.first; \
|
||||
} \
|
||||
auto &entity = C##s[R.first->second]; \
|
||||
RemoveRange(entity.F, it.second.first); \
|
||||
AddRange(entity.F, it.second.second); \
|
||||
@ -250,8 +297,10 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
||||
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
|
||||
auto &entities, auto &p, bool hint_implicit) {
|
||||
auto R = entity_usr.try_emplace(usr, entity_usr.size());
|
||||
if (R.second)
|
||||
entities.emplace_back().usr = usr;
|
||||
if (R.second) {
|
||||
entities.emplace_back();
|
||||
entities.back().usr = usr;
|
||||
}
|
||||
auto &entity = entities[R.first->second];
|
||||
for (Use &use : p.first) {
|
||||
if (hint_implicit && use.role & Role::Implicit) {
|
||||
@ -485,10 +534,10 @@ int ComputeRangeSize(const Range &range) {
|
||||
return range.end.column - range.start.column;
|
||||
}
|
||||
|
||||
template <typename Q>
|
||||
template <typename Q, typename C>
|
||||
std::vector<Use>
|
||||
GetDeclarations(llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
|
||||
std::vector<Q> &entities, const std::vector<Usr> &usrs) {
|
||||
llvm::SmallVectorImpl<Q> &entities, const C &usrs) {
|
||||
std::vector<Use> ret;
|
||||
ret.reserve(usrs.size());
|
||||
for (Usr usr : usrs) {
|
||||
@ -516,6 +565,9 @@ Maybe<DeclRef> GetDefinitionSpell(DB *db, SymbolIdx sym) {
|
||||
std::vector<Use> GetFuncDeclarations(DB *db, const std::vector<Usr> &usrs) {
|
||||
return GetDeclarations(db->func_usr, db->funcs, usrs);
|
||||
}
|
||||
std::vector<Use> GetFuncDeclarations(DB *db, const Vec<Usr> &usrs) {
|
||||
return GetDeclarations(db->func_usr, db->funcs, usrs);
|
||||
}
|
||||
std::vector<Use> GetTypeDeclarations(DB *db, const std::vector<Usr> &usrs) {
|
||||
return GetDeclarations(db->type_usr, db->types, usrs);
|
||||
}
|
||||
|
15
src/query.hh
15
src/query.hh
@ -66,7 +66,7 @@ template <typename T>
|
||||
using Update =
|
||||
std::unordered_map<Usr, std::pair<std::vector<T>, std::vector<T>>>;
|
||||
|
||||
struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
|
||||
struct QueryFunc : QueryEntity<QueryFunc, FuncDef<Vec>> {
|
||||
Usr usr;
|
||||
llvm::SmallVector<Def, 1> def;
|
||||
std::vector<DeclRef> declarations;
|
||||
@ -74,7 +74,7 @@ struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
|
||||
std::vector<Use> uses;
|
||||
};
|
||||
|
||||
struct QueryType : QueryEntity<QueryType, TypeDef> {
|
||||
struct QueryType : QueryEntity<QueryType, TypeDef<Vec>> {
|
||||
Usr usr;
|
||||
llvm::SmallVector<Def, 1> def;
|
||||
std::vector<DeclRef> declarations;
|
||||
@ -147,9 +147,9 @@ struct DB {
|
||||
std::vector<QueryFile> files;
|
||||
llvm::StringMap<int> name2file_id;
|
||||
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> func_usr, type_usr, var_usr;
|
||||
std::vector<QueryFunc> funcs;
|
||||
std::vector<QueryType> types;
|
||||
std::vector<QueryVar> vars;
|
||||
llvm::SmallVector<QueryFunc, 0> funcs;
|
||||
llvm::SmallVector<QueryType, 0> types;
|
||||
llvm::SmallVector<QueryVar, 0> vars;
|
||||
|
||||
void clear();
|
||||
|
||||
@ -188,6 +188,7 @@ Maybe<DeclRef> GetDefinitionSpell(DB *db, SymbolIdx sym);
|
||||
// Get defining declaration (if exists) or an arbitrary declaration (otherwise)
|
||||
// for each id.
|
||||
std::vector<Use> GetFuncDeclarations(DB *, const std::vector<Usr> &);
|
||||
std::vector<Use> GetFuncDeclarations(DB *, const Vec<Usr> &);
|
||||
std::vector<Use> GetTypeDeclarations(DB *, const std::vector<Usr> &);
|
||||
std::vector<DeclRef> GetVarDeclarations(DB *, const std::vector<Usr> &, unsigned);
|
||||
|
||||
@ -257,8 +258,8 @@ void EachOccurrence(DB *db, SymbolIdx sym, bool include_decl, Fn &&fn) {
|
||||
|
||||
SymbolKind GetSymbolKind(DB *db, SymbolIdx sym);
|
||||
|
||||
template <typename Fn>
|
||||
void EachDefinedFunc(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
|
||||
template <typename C, typename Fn>
|
||||
void EachDefinedFunc(DB *db, const C &usrs, Fn &&fn) {
|
||||
for (Usr usr : usrs) {
|
||||
auto &obj = db->Func(usr);
|
||||
if (!obj.def.empty())
|
||||
|
23
src/utils.hh
23
src/utils.hh
@ -128,4 +128,27 @@ public:
|
||||
bool operator==(const Maybe &o) const { return storage == o.storage; }
|
||||
bool operator!=(const Maybe &o) const { return !(*this == o); }
|
||||
};
|
||||
|
||||
template <typename T> struct Vec {
|
||||
std::unique_ptr<T[]> a;
|
||||
int s = 0;
|
||||
#if !(__clang__ || __GNUC__ > 7 || __GNUC__ == 7 && __GNUC_MINOR__ >= 4)
|
||||
// Work around a bug in GCC<7.4 that optional<IndexUpdate> would not be
|
||||
// construtible.
|
||||
Vec() = default;
|
||||
Vec(const Vec &o) : a(std::make_unique<T[]>(o.s)), s(o.s) {
|
||||
std::copy(o.a.get(), o.a.get() + o.s, a.get());
|
||||
}
|
||||
Vec(Vec &&) = default;
|
||||
Vec &operator=(Vec &&) = default;
|
||||
Vec(std::unique_ptr<T[]> a, int s) : a(std::move(a)), s(s) {}
|
||||
#endif
|
||||
const T *begin() const { return a.get(); }
|
||||
T *begin() { return a.get(); }
|
||||
const T *end() const { return a.get() + s; }
|
||||
T *end() { return a.get() + s; }
|
||||
int size() const { return s; }
|
||||
const T &operator[](size_t i) const { return a.get()[i]; }
|
||||
T &operator[](size_t i) { return a.get()[i]; }
|
||||
};
|
||||
} // namespace ccls
|
||||
|
Loading…
Reference in New Issue
Block a user