nridge created this revision.
nridge added a reviewer: kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, ioeric,
ilya-biryukov.
Herald added a project: clang.
RelationSlab is a new index data structure, similar to SymbolSlab and
RefSlab. RelationSlab stores relations between Symbols.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D59407
Files:
clang-tools-extra/clangd/index/Index.cpp
clang-tools-extra/clangd/index/Index.h
Index: clang-tools-extra/clangd/index/Index.h
===================================================================
--- clang-tools-extra/clangd/index/Index.h
+++ clang-tools-extra/clangd/index/Index.h
@@ -22,6 +22,71 @@
namespace clang {
namespace clangd {
+enum class RelationKind { Subtype };
+
+struct RelationKey {
+ SymbolID Symbol;
+ RelationKind Kind;
+
+ bool operator==(const RelationKey &Other) const {
+ return Symbol == Other.Symbol && Kind == Other.Kind;
+ }
+
+private:
+ friend llvm::hash_code hash_value(const RelationKey &Key) {
+ return llvm::hash_combine(Key.Symbol, static_cast<int>(Key.Kind));
+ }
+};
+
+class RelationSlab {
+public:
+ using value_type = std::pair<RelationKey, llvm::ArrayRef<SymbolID>>;
+ using const_iterator = std::vector<value_type>::const_iterator;
+ using iterator = const_iterator;
+
+ RelationSlab() = default;
+ RelationSlab(RelationSlab &&Slab) = default;
+ RelationSlab &operator=(RelationSlab &&RHS) = default;
+
+ const_iterator begin() const { return Relations.begin(); }
+ const_iterator end() const { return Relations.end(); }
+ size_t size() const { return Relations.size(); }
+ size_t numRelations() const { return NumRelations; }
+ bool empty() const { return Relations.empty(); }
+
+ size_t bytes() const {
+ return sizeof(*this) + Arena.getTotalMemory() +
+ sizeof(value_type) * Relations.size();
+ }
+
+ // RelationSlab::Builder is a mutable container that can 'freeze' to
+ // RelationSlab.
+ class Builder {
+ public:
+ Builder() {}
+ // Adds a relation to the slab. Deep copy: Strings will be owned by the
+ // slab.
+ void insert(const RelationKey &Key, const SymbolID &S);
+ // Consumes the builder to finalize the slab.
+ RelationSlab build() &&;
+
+ private:
+ llvm::BumpPtrAllocator Arena;
+ llvm::DenseMap<RelationKey, std::vector<SymbolID>> Relations;
+ };
+
+private:
+ RelationSlab(std::vector<value_type> Relations, llvm::BumpPtrAllocator Arena,
+ size_t NumRelations)
+ : Arena(std::move(Arena)), Relations(std::move(Relations)),
+ NumRelations(NumRelations) {}
+
+ llvm::BumpPtrAllocator Arena;
+ std::vector<value_type> Relations;
+ // Number of all relations.
+ size_t NumRelations = 0;
+};
+
struct FuzzyFindRequest {
/// \brief A query string for the fuzzy find. This is matched against symbols'
/// un-qualified identifiers and should not contain qualifiers like "::".
@@ -136,4 +201,30 @@
} // namespace clangd
} // namespace clang
+namespace llvm {
+
+// Support RelationKeys as DenseMap keys.
+template <> struct DenseMapInfo<clang::clangd::RelationKey> {
+ static inline clang::clangd::RelationKey getEmptyKey() {
+ return {DenseMapInfo<clang::clangd::SymbolID>::getEmptyKey(),
+ clang::clangd::RelationKind::Subtype};
+ }
+
+ static inline clang::clangd::RelationKey getTombstoneKey() {
+ return {DenseMapInfo<clang::clangd::SymbolID>::getTombstoneKey(),
+ clang::clangd::RelationKind::Subtype};
+ }
+
+ static unsigned getHashValue(const clang::clangd::RelationKey &Key) {
+ return hash_value(Key);
+ }
+
+ static bool isEqual(const clang::clangd::RelationKey &LHS,
+ const clang::clangd::RelationKey &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // namespace llvm
+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
Index: clang-tools-extra/clangd/index/Index.cpp
===================================================================
--- clang-tools-extra/clangd/index/Index.cpp
+++ clang-tools-extra/clangd/index/Index.cpp
@@ -17,6 +17,28 @@
namespace clang {
namespace clangd {
+void RelationSlab::Builder::insert(const RelationKey &Key, const SymbolID &S) {
+ Relations[Key].push_back(S);
+}
+
+RelationSlab RelationSlab::Builder::build() && {
+ // Reallocate relations on the arena to reduce waste and indirections when
+ // reading.
+ std::vector<std::pair<RelationKey, llvm::ArrayRef<SymbolID>>> Result;
+ Result.reserve(Relations.size());
+ size_t NumRelations = 0;
+ for (auto &Entry : Relations) {
+ auto &Rels = Entry.second;
+
+ NumRelations += Rels.size();
+ auto *Array = Arena.Allocate<SymbolID>(Rels.size());
+ std::uninitialized_copy(Rels.begin(), Rels.end(), Array);
+ Result.emplace_back(Entry.first,
+ llvm::ArrayRef<SymbolID>(Array, Rels.size()));
+ }
+ return RelationSlab(std::move(Result), std::move(Arena), NumRelations);
+}
+
void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
// Keep the old index alive, so we don't destroy it under lock (may be slow).
std::shared_ptr<SymbolIndex> Pin;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits