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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits