diff options
author | Nico Weber <nicolasweber@gmx.de> | 2015-03-21 04:11:31 (GMT) |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2015-03-21 15:17:02 (GMT) |
commit | 4d44291739222e453421a237ff77d9e5daaa3dd4 (patch) | |
tree | 7cac0876b7ced30ee7034d72874848c1a5dfdeea /src | |
parent | eb7167d456b8ef2dad3846ca2ba6438b060518c9 (diff) | |
download | Ninja-4d44291739222e453421a237ff77d9e5daaa3dd4.zip Ninja-4d44291739222e453421a237ff77d9e5daaa3dd4.tar.gz Ninja-4d44291739222e453421a237ff77d9e5daaa3dd4.tar.bz2 |
Recover slowdown for cyclic rule bindings fix.
Diffstat (limited to 'src')
-rw-r--r-- | src/graph.cc | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/src/graph.cc b/src/graph.cc index 41055ec..d99c8bd 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -217,7 +217,7 @@ struct EdgeEnv : public Env { enum EscapeKind { kShellEscape, kDoNotEscape }; EdgeEnv(Edge* edge, EscapeKind escape) - : edge_(edge), escape_in_out_(escape) {} + : edge_(edge), escape_in_out_(escape), recursive_(false) {} virtual string LookupVariable(const string& var); /// Given a span of Nodes, construct a list of paths suitable for a command @@ -226,9 +226,11 @@ struct EdgeEnv : public Env { vector<Node*>::iterator end, char sep); + private: vector<string> lookups_; Edge* edge_; EscapeKind escape_in_out_; + bool recursive_; }; string EdgeEnv::LookupVariable(const string& var) { @@ -244,19 +246,25 @@ string EdgeEnv::LookupVariable(const string& var) { ' '); } - vector<string>::const_iterator it; - if ((it = find(lookups_.begin(), lookups_.end(), var)) != lookups_.end()) { - string cycle; - for (; it != lookups_.end(); ++it) - cycle.append(*it + " -> "); - cycle.append(var); - Fatal(("cycle in rule variables: " + cycle).c_str()); + if (recursive_) { + vector<string>::const_iterator it; + if ((it = find(lookups_.begin(), lookups_.end(), var)) != lookups_.end()) { + string cycle; + for (; it != lookups_.end(); ++it) + cycle.append(*it + " -> "); + cycle.append(var); + Fatal(("cycle in rule variables: " + cycle).c_str()); + } } // See notes on BindingEnv::LookupWithFallback. const EvalString* eval = edge_->rule_->GetBinding(var); - if (eval) + if (recursive_ && eval) lookups_.push_back(var); + + // In practice, variables defined on rules never use another rule variable. + // For performance, only start checking for cycles after the first lookup. + recursive_ = true; return edge_->env_->LookupWithFallback(var, eval, this); } |