cmAddCustomCommandCommand: store keywords in strings

Callgrind indicated that `strlen` was being called a lot of times here
due to the string comparisons. Since keywords are "sparse" in
`add_custom_command`, use a hash comparison to handle keywords and then
use strings for comparison since they have a built-in length parameter.
This commit is contained in:
Ben Boeckel
2018-01-23 18:29:13 -05:00
committed by Brad King
parent 92cd3d0677
commit c0e7a13702

View File

@@ -3,6 +3,7 @@
#include "cmAddCustomCommandCommand.h"
#include <sstream>
#include <unordered_set>
#include <utility>
#include "cmCustomCommand.h"
@@ -69,57 +70,106 @@ bool cmAddCustomCommandCommand::InitialPass(
tdoing doing = doing_nothing;
for (std::string const& copy : args) {
if (copy == "SOURCE") {
doing = doing_source;
} else if (copy == "COMMAND") {
doing = doing_command;
#define MAKE_STATIC_KEYWORD(KEYWORD) \
static const std::string key##KEYWORD = #KEYWORD
MAKE_STATIC_KEYWORD(APPEND);
MAKE_STATIC_KEYWORD(ARGS);
MAKE_STATIC_KEYWORD(BYPRODUCTS);
MAKE_STATIC_KEYWORD(COMMAND);
MAKE_STATIC_KEYWORD(COMMAND_EXPAND_LISTS);
MAKE_STATIC_KEYWORD(COMMENT);
MAKE_STATIC_KEYWORD(DEPENDS);
MAKE_STATIC_KEYWORD(DEPFILE);
MAKE_STATIC_KEYWORD(IMPLICIT_DEPENDS);
MAKE_STATIC_KEYWORD(MAIN_DEPENDENCY);
MAKE_STATIC_KEYWORD(OUTPUT);
MAKE_STATIC_KEYWORD(OUTPUTS);
MAKE_STATIC_KEYWORD(POST_BUILD);
MAKE_STATIC_KEYWORD(PRE_BUILD);
MAKE_STATIC_KEYWORD(PRE_LINK);
MAKE_STATIC_KEYWORD(SOURCE);
MAKE_STATIC_KEYWORD(TARGET);
MAKE_STATIC_KEYWORD(USES_TERMINAL);
MAKE_STATIC_KEYWORD(VERBATIM);
MAKE_STATIC_KEYWORD(WORKING_DIRECTORY);
#undef MAKE_STATIC_KEYWORD
static std::unordered_set<std::string> keywords;
if (keywords.empty()) {
keywords.insert(keyAPPEND);
keywords.insert(keyARGS);
keywords.insert(keyBYPRODUCTS);
keywords.insert(keyCOMMAND);
keywords.insert(keyCOMMAND_EXPAND_LISTS);
keywords.insert(keyCOMMENT);
keywords.insert(keyDEPENDS);
keywords.insert(keyDEPFILE);
keywords.insert(keyIMPLICIT_DEPENDS);
keywords.insert(keyMAIN_DEPENDENCY);
keywords.insert(keyOUTPUT);
keywords.insert(keyOUTPUTS);
keywords.insert(keyPOST_BUILD);
keywords.insert(keyPRE_BUILD);
keywords.insert(keyPRE_LINK);
keywords.insert(keySOURCE);
keywords.insert(keyTARGET);
keywords.insert(keyUSES_TERMINAL);
keywords.insert(keyVERBATIM);
keywords.insert(keyWORKING_DIRECTORY);
}
// Save the current command before starting the next command.
if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
}
} else if (copy == "PRE_BUILD") {
cctype = cmTarget::PRE_BUILD;
} else if (copy == "PRE_LINK") {
cctype = cmTarget::PRE_LINK;
} else if (copy == "POST_BUILD") {
cctype = cmTarget::POST_BUILD;
} else if (copy == "VERBATIM") {
verbatim = true;
} else if (copy == "APPEND") {
append = true;
} else if (copy == "USES_TERMINAL") {
uses_terminal = true;
} else if (copy == "COMMAND_EXPAND_LISTS") {
command_expand_lists = true;
} else if (copy == "TARGET") {
doing = doing_target;
} else if (copy == "ARGS") {
// Ignore this old keyword.
} else if (copy == "DEPENDS") {
doing = doing_depends;
} else if (copy == "OUTPUTS") {
doing = doing_outputs;
} else if (copy == "OUTPUT") {
doing = doing_output;
} else if (copy == "BYPRODUCTS") {
doing = doing_byproducts;
} else if (copy == "WORKING_DIRECTORY") {
doing = doing_working_directory;
} else if (copy == "MAIN_DEPENDENCY") {
doing = doing_main_dependency;
} else if (copy == "IMPLICIT_DEPENDS") {
doing = doing_implicit_depends_lang;
} else if (copy == "COMMENT") {
doing = doing_comment;
} else if (copy == "DEPFILE") {
doing = doing_depfile;
if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") {
this->SetError("Option DEPFILE not supported by " +
this->Makefile->GetGlobalGenerator()->GetName());
return false;
for (std::string const& copy : args) {
if (keywords.count(copy)) {
if (copy == keySOURCE) {
doing = doing_source;
} else if (copy == keyCOMMAND) {
doing = doing_command;
// Save the current command before starting the next command.
if (!currentLine.empty()) {
commandLines.push_back(currentLine);
currentLine.clear();
}
} else if (copy == keyPRE_BUILD) {
cctype = cmTarget::PRE_BUILD;
} else if (copy == keyPRE_LINK) {
cctype = cmTarget::PRE_LINK;
} else if (copy == keyPOST_BUILD) {
cctype = cmTarget::POST_BUILD;
} else if (copy == keyVERBATIM) {
verbatim = true;
} else if (copy == keyAPPEND) {
append = true;
} else if (copy == keyUSES_TERMINAL) {
uses_terminal = true;
} else if (copy == keyCOMMAND_EXPAND_LISTS) {
command_expand_lists = true;
} else if (copy == keyTARGET) {
doing = doing_target;
} else if (copy == keyARGS) {
// Ignore this old keyword.
} else if (copy == keyDEPENDS) {
doing = doing_depends;
} else if (copy == keyOUTPUTS) {
doing = doing_outputs;
} else if (copy == keyOUTPUT) {
doing = doing_output;
} else if (copy == keyBYPRODUCTS) {
doing = doing_byproducts;
} else if (copy == keyWORKING_DIRECTORY) {
doing = doing_working_directory;
} else if (copy == keyMAIN_DEPENDENCY) {
doing = doing_main_dependency;
} else if (copy == keyIMPLICIT_DEPENDS) {
doing = doing_implicit_depends_lang;
} else if (copy == keyCOMMENT) {
doing = doing_comment;
} else if (copy == keyDEPFILE) {
doing = doing_depfile;
if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") {
this->SetError("Option DEPFILE not supported by " +
this->Makefile->GetGlobalGenerator()->GetName());
return false;
}
}
} else {
std::string filename;