r247018 - Fix performance regression when running clang tools.
Manuel Klimek via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 8 08:14:06 PDT 2015
Author: klimek
Date: Tue Sep 8 10:14:06 2015
New Revision: 247018
URL: http://llvm.org/viewvc/llvm-project?rev=247018&view=rev
Log:
Fix performance regression when running clang tools.
Brings tool start time for a large synthetic test case down from (on my
machine) 4 seconds to 0.5 seconds.
Modified:
cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h
cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp
cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp
Modified: cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h?rev=247018&r1=247017&r2=247018&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h (original)
+++ cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h Tue Sep 8 10:14:06 2015
@@ -99,17 +99,21 @@ private:
/// failed.
bool parse(std::string &ErrorMessage);
- // Tuple (directory, commandline) where 'commandline' pointing to the
- // corresponding nodes in the YAML stream.
- typedef std::pair<llvm::yaml::ScalarNode*,
- std::vector<std::string>> CompileCommandRef;
+ // Tuple (directory, commandline) where 'commandline' points to the
+ // corresponding scalar nodes in the YAML stream.
+ // If the command line contains a single argument, it is a shell-escaped
+ // command line.
+ // Otherwise, each entry in the command line vector is a literal
+ // argument to the compiler.
+ typedef std::pair<llvm::yaml::ScalarNode *,
+ std::vector<llvm::yaml::ScalarNode *>> CompileCommandRef;
/// \brief Converts the given array of CompileCommandRefs to CompileCommands.
void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
std::vector<CompileCommand> &Commands) const;
// Maps file paths to the compile command lines for that file.
- llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
+ llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile;
FileMatchTrie MatchTrie;
Modified: cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp?rev=247018&r1=247017&r2=247018&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp (original)
+++ cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp Tue Sep 8 10:14:06 2015
@@ -214,15 +214,26 @@ JSONCompilationDatabase::getAllCompileCo
return Commands;
}
+static std::vector<std::string>
+nodeToCommandLine(const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
+ SmallString<1024> Storage;
+ if (Nodes.size() == 1) {
+ return unescapeCommandLine(Nodes[0]->getValue(Storage));
+ }
+ std::vector<std::string> Arguments;
+ for (auto *Node : Nodes) {
+ Arguments.push_back(Node->getValue(Storage));
+ }
+ return Arguments;
+}
+
void JSONCompilationDatabase::getCommands(
- ArrayRef<CompileCommandRef> CommandsRef,
- std::vector<CompileCommand> &Commands) const {
+ ArrayRef<CompileCommandRef> CommandsRef,
+ std::vector<CompileCommand> &Commands) const {
for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
SmallString<8> DirectoryStorage;
- SmallString<1024> CommandStorage;
- Commands.emplace_back(
- CommandsRef[I].first->getValue(DirectoryStorage),
- CommandsRef[I].second);
+ Commands.emplace_back(CommandsRef[I].first->getValue(DirectoryStorage),
+ nodeToCommandLine(CommandsRef[I].second));
}
}
@@ -249,11 +260,8 @@ bool JSONCompilationDatabase::parse(std:
return false;
}
llvm::yaml::ScalarNode *Directory = nullptr;
- std::vector<std::string> Arguments;
- std::vector<std::string> Command;
+ llvm::Optional<std::vector<llvm::yaml::ScalarNode *>> Command;
llvm::yaml::ScalarNode *File = nullptr;
- bool ArgumentsFound = false;
- bool CommandFound = false;
for (auto& NextKeyValue : *Object) {
llvm::yaml::ScalarNode *KeyString =
dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -282,18 +290,18 @@ bool JSONCompilationDatabase::parse(std:
if (KeyValue == "directory") {
Directory = ValueString;
} else if (KeyValue == "arguments") {
- for (auto& NextArgument : *SequenceString) {
- SmallString<128> CommandStorage;
- auto ValueString = dyn_cast<llvm::yaml::ScalarNode>(&NextArgument);
-
- Arguments.push_back(ValueString->getValue(CommandStorage));
+ Command = std::vector<llvm::yaml::ScalarNode *>();
+ for (auto &Argument : *SequenceString) {
+ auto Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
+ if (!Scalar) {
+ ErrorMessage = "Only strings are allowed in 'arguments'.";
+ return false;
+ }
+ Command->push_back(Scalar);
}
- ArgumentsFound = true;
} else if (KeyValue == "command") {
- SmallString<1024> CommandStorage;
- // FIXME: Escape correctly:
- Command = unescapeCommandLine(ValueString->getValue(CommandStorage));
- CommandFound = true;
+ if (!Command)
+ Command = std::vector<llvm::yaml::ScalarNode *>(1, ValueString);
} else if (KeyValue == "file") {
File = ValueString;
} else {
@@ -306,7 +314,7 @@ bool JSONCompilationDatabase::parse(std:
ErrorMessage = "Missing key: \"file\".";
return false;
}
- if (!ArgumentsFound && !CommandFound) {
+ if (!Command) {
ErrorMessage = "Missing key: \"command\" or \"arguments\".";
return false;
}
@@ -327,7 +335,7 @@ bool JSONCompilationDatabase::parse(std:
llvm::sys::path::native(FileName, NativeFilePath);
}
IndexByFile[NativeFilePath].push_back(
- CompileCommandRef(Directory, ArgumentsFound ? Arguments : Command));
+ CompileCommandRef(Directory, *Command));
MatchTrie.insert(NativeFilePath);
}
return true;
Modified: cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp?rev=247018&r1=247017&r2=247018&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp Tue Sep 8 10:14:06 2015
@@ -42,6 +42,8 @@ TEST(JSONCompilationDatabase, ErrsOnInva
expectFailure("[{\"arguments\":\"\",\"file\":\"\"}]", "Missing directory");
expectFailure("[{\"directory\":\"\",\"arguments\":\"\",\"file\":\"\"}]", "Arguments not array");
expectFailure("[{\"directory\":\"\",\"command\":[],\"file\":\"\"}]", "Command not string");
+ expectFailure("[{\"directory\":\"\",\"arguments\":[[]],\"file\":\"\"}]",
+ "Arguments contain non-string");
}
static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
@@ -140,8 +142,8 @@ TEST(JSONCompilationDatabase, ArgumentsP
CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
FileName,
("[{\"directory\":\"" + Directory + "\","
- "\"command\":\"" + Command + "\","
"\"arguments\":[\"" + Arguments + "\"],"
+ "\"command\":\"" + Command + "\","
"\"file\":\"" + FileName + "\"}]").str(),
ErrorMessage);
EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
More information about the cfe-commits
mailing list