[clang] c1bbefe - [Syntax] Use a hash table to search for tokens by their location

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 18 03:24:31 PST 2019


Author: Ilya Biryukov
Date: 2019-12-18T12:24:00+01:00
New Revision: c1bbefef9d36e84e469513374ef404b9e354b262

URL: https://github.com/llvm/llvm-project/commit/c1bbefef9d36e84e469513374ef404b9e354b262
DIFF: https://github.com/llvm/llvm-project/commit/c1bbefef9d36e84e469513374ef404b9e354b262.diff

LOG: [Syntax] Use a hash table to search for tokens by their location

This is both more efficient and avoids corner cases in
`SourceManager::isBeforeInTranslationUnit`.

The change is trivial and clearly a performance improvement on the hot
path of building the syntax tree, so sending without review.

Added: 
    

Modified: 
    clang/lib/Tooling/Syntax/BuildTree.cpp
    clang/unittests/Tooling/Syntax/TreeTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 6f8a42a1ff13..f61c5ff39e1c 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -51,7 +51,10 @@ static bool isImplicitExpr(clang::Expr *E) { return E->IgnoreImplicit() != E; }
 /// Call finalize() to finish building the tree and consume the root node.
 class syntax::TreeBuilder {
 public:
-  TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) {}
+  TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) {
+    for (const auto &T : Arena.tokenBuffer().expandedTokens())
+      LocationToToken.insert({T.location().getRawEncoding(), &T});
+  }
 
   llvm::BumpPtrAllocator &allocator() { return Arena.allocator(); }
 
@@ -304,6 +307,9 @@ class syntax::TreeBuilder {
   std::string str() { return Pending.str(Arena); }
 
   syntax::Arena &Arena;
+  /// To quickly find tokens by their start location.
+  llvm::DenseMap</*SourceLocation*/ unsigned, const syntax::Token *>
+      LocationToToken;
   Forest Pending;
   llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
 };
@@ -641,14 +647,9 @@ void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
 }
 
 const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
-  auto Tokens = Arena.tokenBuffer().expandedTokens();
-  auto &SM = Arena.sourceManager();
-  auto It = llvm::partition_point(Tokens, [&](const syntax::Token &T) {
-    return SM.isBeforeInTranslationUnit(T.location(), L);
-  });
-  assert(It != Tokens.end());
-  assert(It->location() == L);
-  return &*It;
+  auto It = LocationToToken.find(L.getRawEncoding());
+  assert(It != LocationToToken.end());
+  return It->second;
 }
 
 syntax::TranslationUnit *

diff  --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp
index bcc6f29c6468..4de353091cdc 100644
--- a/clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -767,6 +767,46 @@ void test() {
     | `-CompoundStatement
     |   |-{
     |   `-}
+    `-}
+       )txt"},
+      // All nodes can be mutated.
+      {R"cpp(
+#define OPEN {
+#define CLOSE }
+
+void test() {
+  OPEN
+    1;
+  CLOSE
+
+  OPEN
+    2;
+  }
+}
+)cpp",
+       R"txt(
+*: TranslationUnit
+`-SimpleDeclaration
+  |-void
+  |-test
+  |-(
+  |-)
+  `-CompoundStatement
+    |-{
+    |-CompoundStatement
+    | |-{
+    | |-ExpressionStatement
+    | | |-UnknownExpression
+    | | | `-1
+    | | `-;
+    | `-}
+    |-CompoundStatement
+    | |-{
+    | |-ExpressionStatement
+    | | |-UnknownExpression
+    | | | `-2
+    | | `-;
+    | `-}
     `-}
        )txt"},
   };


        


More information about the cfe-commits mailing list