diff options
author | Shinichiro Hamaji <hamaji@google.com> | 2016-02-28 04:40:46 +0000 |
---|---|---|
committer | Shinichiro Hamaji <hamaji@google.com> | 2016-02-28 04:40:46 +0000 |
commit | 086b17663573f0d2742c534885a787c6d98216b9 (patch) | |
tree | 5618f6c181f4685b721fb141b59dfbbd691ce12b | |
parent | 59ce30d7b247cfc41950e2cc5438a1bff66bdc1f (diff) | |
download | kati-086b17663573f0d2742c534885a787c6d98216b9.tar.gz |
Revert "Merge remote-tracking branch 'aosp/upstream'"
This reverts commit 59ce30d7b247cfc41950e2cc5438a1bff66bdc1f.
This looks the culprit of b/27381403. As I haven't figured out
the cause yet, let's just revert this for now.
Bug: 27381403
Change-Id: Ifd25a24b4bd7f2922ce76d6a05f85723074848ea
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | Makefile.ckati | 1 | ||||
-rw-r--r-- | affinity.cc | 50 | ||||
-rw-r--r-- | affinity.h | 21 | ||||
-rw-r--r-- | condvar.cc | 4 | ||||
-rw-r--r-- | condvar.h | 2 | ||||
-rw-r--r-- | dep.cc | 40 | ||||
-rw-r--r-- | dep.h | 3 | ||||
-rw-r--r-- | eval.cc | 25 | ||||
-rw-r--r-- | eval.h | 15 | ||||
-rw-r--r-- | expr.cc | 5 | ||||
-rw-r--r-- | expr.h | 2 | ||||
-rw-r--r-- | file_cache.cc | 2 | ||||
-rw-r--r-- | fileutil.cc | 11 | ||||
-rw-r--r-- | find.cc | 10 | ||||
-rw-r--r-- | flags.cc | 2 | ||||
-rw-r--r-- | flags.h | 1 | ||||
-rw-r--r-- | func.cc | 25 | ||||
-rw-r--r-- | main.cc | 14 | ||||
-rw-r--r-- | mutex.cc | 8 | ||||
-rw-r--r-- | mutex.h | 14 | ||||
-rw-r--r-- | ninja.cc | 234 | ||||
-rw-r--r-- | regen.cc | 6 | ||||
-rwxr-xr-x | run_integration_test.rb | 182 | ||||
-rwxr-xr-x | runtest.rb | 1 | ||||
-rw-r--r-- | stats.cc | 26 | ||||
-rw-r--r-- | stats.h | 2 | ||||
-rw-r--r-- | stmt.cc | 13 | ||||
-rw-r--r-- | stmt.h | 9 | ||||
-rw-r--r-- | string_piece.cc | 12 | ||||
-rw-r--r-- | string_piece_test.cc | 4 | ||||
-rw-r--r-- | strutil.cc | 61 | ||||
-rw-r--r-- | strutil.h | 2 | ||||
-rw-r--r-- | symtab.cc | 17 | ||||
-rw-r--r-- | testcase/ninja_mkdir.sh | 42 | ||||
-rw-r--r-- | testcase/shell_var_with_args.mk | 9 | ||||
-rw-r--r-- | testcase/sort.mk | 7 | ||||
-rw-r--r-- | thread_local.h | 11 | ||||
-rw-r--r-- | thread_pool.cc | 12 | ||||
-rw-r--r-- | var.cc | 8 | ||||
-rw-r--r-- | var.h | 31 |
41 files changed, 405 insertions, 540 deletions
@@ -15,7 +15,6 @@ cc_library_host_static { name: "libckati", srcs: [ - "affinity.cc", "command.cc", "condvar.cc", "dep.cc", diff --git a/Makefile.ckati b/Makefile.ckati index 38e1feb..cf5bab8 100644 --- a/Makefile.ckati +++ b/Makefile.ckati @@ -22,7 +22,6 @@ KATI_INTERMEDIATES_PATH ?= . KATI_BIN_PATH ?= . KATI_CXX_SRCS := \ - affinity.cc \ command.cc \ condvar.cc \ dep.cc \ diff --git a/affinity.cc b/affinity.cc deleted file mode 100644 index 0743f94..0000000 --- a/affinity.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "affinity.h" - -#include "flags.h" -#include "log.h" - -#ifdef __linux__ - -#include <sched.h> - -void SetAffinityForSingleThread() { - cpu_set_t cs; - CPU_ZERO(&cs); - int n = g_flags.num_cpus / 2; - CPU_SET(n, &cs); - if (n > 1) - CPU_SET(n + 1, &cs); - if (sched_setaffinity(0, sizeof(cs), &cs) < 0) - WARN("sched_setaffinity: %s", strerror(errno)); -} - -void SetAffinityForMultiThread() { - cpu_set_t cs; - CPU_ZERO(&cs); - for (int i = 0; i < g_flags.num_cpus; i++) { - CPU_SET(i, &cs); - } - if (sched_setaffinity(0, sizeof(cs), &cs) < 0) - WARN("sched_setaffinity: %s", strerror(errno)); -} - -#else - -void SetAffinityForSingleThread() {} -void SetAffinityForMultiThread() {} - -#endif diff --git a/affinity.h b/affinity.h deleted file mode 100644 index e6f6adc..0000000 --- a/affinity.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef AFFINITY_H_ -#define AFFINITY_H_ - -void SetAffinityForSingleThread(); -void SetAffinityForMultiThread(); - -#endif @@ -26,8 +26,8 @@ condition_variable::~condition_variable() { PERROR("pthread_cond_destroy"); } -void condition_variable::wait(const UniqueLock<Mutex>& mu) { - if (pthread_cond_wait(&cond_, &mu.Mutex()->mu_) != 0) +void condition_variable::wait(const unique_lock<mutex>& mu) { + if (pthread_cond_wait(&cond_, &mu.mutex()->mu_) != 0) PERROR("pthread_cond_wait"); } @@ -24,7 +24,7 @@ class condition_variable { condition_variable(); ~condition_variable(); - void wait(const UniqueLock<Mutex>& mu); + void wait(const unique_lock<mutex>& mu); void notify_one(); void notify_all(); @@ -27,10 +27,8 @@ #include "fileutil.h" #include "log.h" #include "rule.h" -#include "stats.h" #include "strutil.h" #include "symtab.h" -#include "timeutil.h" #include "var.h" namespace { @@ -118,14 +116,13 @@ DepNode::DepNode(Symbol o, bool p, bool r) class DepBuilder { public: DepBuilder(Evaluator* ev, - const vector<const Rule*>& rules, + const vector<shared_ptr<Rule>>& rules, const unordered_map<Symbol, Vars*>& rule_vars) : ev_(ev), rule_vars_(rule_vars), implicit_rules_(new RuleTrie()), first_rule_(NULL), depfile_var_name_(Intern(".KATI_DEPFILE")) { - ScopedTimeReporter tr("make dep (populate)"); PopulateRules(rules); LOG_STAT("%zu variables", ev->mutable_vars()->size()); LOG_STAT("%zu explicit rules", rules_.size()); @@ -229,8 +226,8 @@ class DepBuilder { return ::Exists(target.str()); } - void PopulateRules(const vector<const Rule*>& rules) { - for (const Rule* rule : rules) { + void PopulateRules(const vector<shared_ptr<Rule>>& rules) { + for (shared_ptr<Rule> rule : rules) { if (rule->outputs.empty()) { PopulateImplicitRule(rule); } else { @@ -242,7 +239,7 @@ class DepBuilder { } } - bool PopulateSuffixRule(const Rule* rule, Symbol output) { + bool PopulateSuffixRule(shared_ptr<Rule> rule, Symbol output) { if (output.empty() || output.str()[0] != '.') return false; @@ -294,7 +291,6 @@ class DepBuilder { const Rule& rule, Symbol output, bool is_suffix_rule) { - COLLECT_STATS("make dep (merge rule)"); if (old_rule.is_double_colon != rule.is_double_colon) { ERROR("%s:%d: *** target file `%s' has both : and :: entries.", LOCF(rule.loc), output.str().c_str()); @@ -341,7 +337,7 @@ class DepBuilder { return r; } - void PopulateExplicitRule(const Rule* orig_rule) { + void PopulateExplicitRule(shared_ptr<Rule> orig_rule) { for (Symbol output : orig_rule->outputs) { const bool is_suffix_rule = PopulateSuffixRule(orig_rule, output); @@ -349,7 +345,7 @@ class DepBuilder { rule->outputs.clear(); rule->outputs.push_back(output); - auto p = rules_.emplace(output, rule); + auto p = rules_.insert(make_pair(output, rule)); if (p.second) { if (!first_rule_ && output.get(0) != '.') { rule->is_default_target = true; @@ -362,24 +358,9 @@ class DepBuilder { } } - static bool IsIgnorableImplicitRule(const Rule* rule) { - // As kati doesn't have RCS/SCCS related default rules, we can - // safely ignore suppression for them. - if (rule->inputs.size() != 1) - return false; - if (!rule->order_only_inputs.empty()) - return false; - if (!rule->cmds.empty()) - return false; - const string& i = rule->inputs[0].str(); - return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" || - i == "s.%" || i == "SCCS/s.%"); - } - - void PopulateImplicitRule(const Rule* rule) { + void PopulateImplicitRule(shared_ptr<Rule> rule) { for (Symbol output_pattern : rule->output_patterns) { - if (output_pattern.str() != "%" || !IsIgnorableImplicitRule(rule)) - implicit_rules_->Add(output_pattern.str(), rule); + implicit_rules_->Add(output_pattern.str(), rule.get()); } } @@ -456,7 +437,6 @@ class DepBuilder { bool PickRule(Symbol output, DepNode* n, shared_ptr<Rule>* out_rule, Vars** out_var) { - COLLECT_STATS("make dep (pick rule)"); shared_ptr<Rule> rule = LookupRule(output); Vars* vars = LookupRuleVars(output); *out_rule = rule; @@ -559,7 +539,6 @@ class DepBuilder { vector<unique_ptr<ScopedVar>> sv; if (vars) { - COLLECT_STATS("make dep (create scope)"); for (const auto& p : *vars) { Symbol name = p.first; RuleVar* var = reinterpret_cast<RuleVar*>(p.second); @@ -640,12 +619,11 @@ class DepBuilder { }; void MakeDep(Evaluator* ev, - const vector<const Rule*>& rules, + const vector<shared_ptr<Rule>>& rules, const unordered_map<Symbol, Vars*>& rule_vars, const vector<Symbol>& targets, vector<DepNode*>* nodes) { DepBuilder db(ev, rules, rule_vars); - ScopedTimeReporter tr("make dep (build)"); db.Build(targets, nodes); } @@ -15,6 +15,7 @@ #ifndef DEP_H_ #define DEP_H_ +#include <memory> #include <string> #include <unordered_map> #include <vector> @@ -52,7 +53,7 @@ void InitDepNodePool(); void QuitDepNodePool(); void MakeDep(Evaluator* ev, - const vector<const Rule*>& rules, + const vector<shared_ptr<Rule>>& rules, const unordered_map<Symbol, Vars*>& rule_vars, const vector<Symbol>& targets, vector<DepNode*>* nodes); @@ -30,8 +30,15 @@ #include "symtab.h" #include "var.h" +EvalResult::~EvalResult() { + for (auto p : rule_vars) + delete p.second; + delete vars; +} + Evaluator::Evaluator(const Vars* vars) - : vars_(new Vars(*vars)), + : in_vars_(vars), + vars_(new Vars()), last_rule_(NULL), current_scope_(NULL), avoid_io_(false), @@ -54,12 +61,9 @@ Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs, Var* rhs = NULL; bool needs_assign = true; switch (op) { - case AssignOp::COLON_EQ: { - SimpleVar* sv = new SimpleVar(origin); - rhs_v->Eval(this, sv->mutable_value()); - rhs = sv; + case AssignOp::COLON_EQ: + rhs = new SimpleVar(rhs_v->Eval(this), origin); break; - } case AssignOp::EQ: rhs = new RecursiveVar(rhs_v, origin, orig_rhs); break; @@ -96,7 +100,7 @@ Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs, void Evaluator::EvalAssign(const AssignStmt* stmt) { loc_ = stmt->loc(); last_rule_ = NULL; - Symbol lhs = stmt->GetLhsSymbol(this); + Symbol lhs = Intern(stmt->lhs->Eval(this)); if (lhs.empty()) Error("*** empty variable name."); Var* rhs = EvalRHS(lhs, stmt->rhs, stmt->orig_rhs, stmt->op, @@ -127,12 +131,11 @@ void Evaluator::EvalRule(const RuleStmt* stmt) { } LOG("Rule: %s", rule->DebugString().c_str()); - rules_.push_back(rule); + rules_.push_back(shared_ptr<Rule>(rule)); last_rule_ = rule; return; } - Symbol lhs = Intern(rule_var.lhs); for (Symbol output : rule_var.outputs) { auto p = rule_vars_.emplace(output, nullptr); if (p.second) { @@ -156,6 +159,7 @@ void Evaluator::EvalRule(const RuleStmt* stmt) { } current_scope_ = p.first->second; + Symbol lhs = Intern(rule_var.lhs); Var* rhs_var = EvalRHS(lhs, rhs, StringPiece("*TODO*"), rule_var.op); if (rhs_var) current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op)); @@ -287,6 +291,9 @@ Var* Evaluator::LookupVarGlobal(Symbol name) { Var* v = vars_->Lookup(name); if (v->IsDefined()) return v; + v = in_vars_->Lookup(name); + if (v->IsDefined()) + return v; used_undefined_vars_.insert(name); return v; } @@ -15,6 +15,7 @@ #ifndef EVAL_H_ #define EVAL_H_ +#include <memory> #include <unordered_map> #include <unordered_set> #include <vector> @@ -31,6 +32,15 @@ class Rule; class Var; class Vars; +struct EvalResult { + ~EvalResult(); + vector<shared_ptr<Rule>> rules; + Vars* vars; + unordered_map<StringPiece, Vars*> rule_vars; + // TODO: read_mks + unordered_map<StringPiece, bool> exports; +}; + class Evaluator { public: Evaluator(const Vars* vars); @@ -52,7 +62,7 @@ class Evaluator { const Loc& loc() const { return loc_; } void set_loc(const Loc& loc) { loc_ = loc; } - const vector<const Rule*>& rules() const { return rules_; } + const vector<shared_ptr<Rule>>& rules() const { return rules_; } const unordered_map<Symbol, Vars*>& rule_vars() const { return rule_vars_; } @@ -97,9 +107,10 @@ class Evaluator { Var* LookupVarGlobal(Symbol name); + const Vars* in_vars_; Vars* vars_; unordered_map<Symbol, Vars*> rule_vars_; - vector<const Rule*> rules_; + vector<shared_ptr<Rule>> rules_; unordered_map<Symbol, bool> exports_; Rule* last_rule_; @@ -62,8 +62,7 @@ class Literal : public Value { s->append(s_.begin(), s_.end()); } - virtual bool IsLiteral() const override { return true; } - virtual StringPiece GetLiteralValueUnsafe() const { return s_; } + virtual bool IsLiteral() const { return true; } virtual string DebugString_() const override { return s_.as_string(); @@ -110,7 +109,7 @@ class Expr : public Value { return r; } - virtual Value* Compact() override { + virtual Value* Compact() { if (vals_.size() != 1) { return this; } @@ -42,8 +42,6 @@ class Value : public Evaluable { virtual Value* Compact() { return this; } virtual bool IsLiteral() const { return false; } - // Only safe after IsLiteral() returns true. - virtual StringPiece GetLiteralValueUnsafe() const { return ""; } string DebugString() const; diff --git a/file_cache.cc b/file_cache.cc index afdb3bd..6a05550 100644 --- a/file_cache.cc +++ b/file_cache.cc @@ -44,7 +44,7 @@ class MakefileCacheManagerImpl : public MakefileCacheManager { virtual Makefile* ReadMakefile(const string& filename) override { Makefile* result = NULL; - auto p = cache_.emplace(filename, result); + auto p = cache_.insert(make_pair(filename, result)); if (p.second) { p.first->second = result = new Makefile(filename); } else { diff --git a/fileutil.cc b/fileutil.cc index a2a0d09..42e81a2 100644 --- a/fileutil.cc +++ b/fileutil.cc @@ -32,7 +32,6 @@ #include <unordered_map> #include "log.h" -#include "strutil.h" bool Exists(StringPiece filename) { CHECK(filename.size() < PATH_MAX); @@ -63,13 +62,6 @@ double GetTimestamp(StringPiece filename) { int RunCommand(const string& shell, const string& cmd, RedirectStderr redirect_stderr, string* s) { - string cmd_escaped = cmd; - EscapeShell(&cmd_escaped); - string cmd_with_shell = shell + " -c \"" + cmd_escaped + "\""; - const char* argv[] = { - "/bin/sh", "-c", cmd_with_shell.c_str(), NULL - }; - int pipefd[2]; if (pipe(pipefd) != 0) PERROR("pipe failed"); @@ -114,6 +106,9 @@ int RunCommand(const string& shell, const string& cmd, PERROR("dup2 failed"); close(pipefd[1]); + const char* argv[] = { + shell.c_str(), "-c", cmd.c_str(), NULL + }; execvp(argv[0], const_cast<char**>(argv)); PLOG("execvp for %s failed", argv[0]); kill(getppid(), SIGTERM); @@ -154,7 +154,7 @@ class DirentFileNode : public DirentNode { virtual bool RunFind(const FindCommand& fc, int d, string* path, unordered_map<const DirentNode*, string>*, - string* out) const override { + string* out) const { PrintIfNecessary(fc, *path, type_, d, out); return true; } @@ -205,7 +205,7 @@ class DirentDirNode : public DirentNode { } } - virtual const DirentNode* FindDir(StringPiece d) const override { + virtual const DirentNode* FindDir(StringPiece d) const { if (d.empty() || d == ".") return this; size_t index = d.find('/'); @@ -224,7 +224,7 @@ class DirentDirNode : public DirentNode { virtual bool RunFind(const FindCommand& fc, int d, string* path, unordered_map<const DirentNode*, string>* cur_read_dirs, - string* out) const override { + string* out) const { ScopedReadDirTracker srdt(this, *path, cur_read_dirs); if (!srdt.ok()) { fprintf(stderr, "FindEmulator: find: File system loop detected; `%s' is " @@ -308,7 +308,7 @@ class DirentSymlinkNode : public DirentNode { : DirentNode(name), to_(NULL), errno_(0) { } - virtual const DirentNode* FindDir(StringPiece d) const override { + virtual const DirentNode* FindDir(StringPiece d) const { if (errno_ == 0 && to_) return to_->FindDir(d); return NULL; @@ -317,7 +317,7 @@ class DirentSymlinkNode : public DirentNode { virtual bool RunFind(const FindCommand& fc, int d, string* path, unordered_map<const DirentNode*, string>* cur_read_dirs, - string* out) const override { + string* out) const { unsigned char type = DT_LNK; if (fc.follows_symlinks && errno_ != ENOENT) { if (errno_) { @@ -49,7 +49,7 @@ static bool ParseCommandLineOptionWithArg(StringPiece option, void Flags::Parse(int argc, char** argv) { subkati_args.push_back(argv[0]); - num_jobs = num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + num_jobs = sysconf(_SC_NPROCESSORS_ONLN); const char* num_jobs_str; for (int i = 1; i < argc; i++) { @@ -44,7 +44,6 @@ struct Flags { const char* makefile; const char* ninja_dir; const char* ninja_suffix; - int num_cpus; int num_jobs; int remote_num_jobs; vector<const char*> subkati_args; @@ -182,14 +182,10 @@ void FilterOutFunc(const vector<Value*>& args, Evaluator* ev, string* s) { } void SortFunc(const vector<Value*>& args, Evaluator* ev, string* s) { - string list; - args[0]->Eval(ev, &list); - COLLECT_STATS("func sort time"); - // TODO(hamaji): Probably we could use a faster string-specific sort - // algorithm. + const string&& list = args[0]->Eval(ev); vector<StringPiece> toks; WordScanner(list).Split(&toks); - stable_sort(toks.begin(), toks.end()); + sort(toks.begin(), toks.end()); WordWriter ww(s); StringPiece prev; for (StringPiece tok : toks) { @@ -578,9 +574,8 @@ void ShellFunc(const vector<Value*>& args, Evaluator* ev, string* s) { } void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) { - static const Symbol tmpvar_names[] = { - Intern("0"), Intern("1"), Intern("2"), Intern("3"), Intern("4"), - Intern("5"), Intern("6"), Intern("7"), Intern("8"), Intern("9") + static const string tmpvar_names[] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; const string&& func_name = args[0]->Eval(ev); @@ -598,25 +593,25 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) { vector<unique_ptr<ScopedVar>> sv; for (size_t i = 1; ; i++) { string s; - Symbol tmpvar_name_sym(Symbol::IsUninitialized{}); + StringPiece tmpvar_name; if (i < sizeof(tmpvar_names)/sizeof(tmpvar_names[0])) { - tmpvar_name_sym = tmpvar_names[i]; + tmpvar_name = tmpvar_names[i]; } else { s = StringPrintf("%d", i); - tmpvar_name_sym = Intern(s); + tmpvar_name = s; } if (i < args.size()) { sv.emplace_back(new ScopedVar(ev->mutable_vars(), - tmpvar_name_sym, av[i-1].get())); + Intern(tmpvar_name), av[i-1].get())); } else { // We need to blank further automatic vars - Var *v = ev->LookupVar(tmpvar_name_sym); + Var *v = ev->LookupVar(Intern(tmpvar_name)); if (!v->IsDefined()) break; if (v->Origin() != VarOrigin::AUTOMATIC) break; av.emplace_back(new SimpleVar("", VarOrigin::AUTOMATIC)); sv.emplace_back(new ScopedVar(ev->mutable_vars(), - tmpvar_name_sym, av[i-1].get())); + Intern(tmpvar_name), av[i-1].get())); } } @@ -21,7 +21,6 @@ #include <time.h> #include <unistd.h> -#include "affinity.h" #include "dep.h" #include "eval.h" #include "exec.h" @@ -124,7 +123,7 @@ static int Run(const vector<Symbol>& targets, if (g_flags.generate_ninja && (g_flags.regen || g_flags.dump_kati_stamp)) { ScopedTimeReporter tr("regen check time"); if (!NeedsRegen(start_time, orig_args)) { - fprintf(stderr, "No need to regenerate ninja file\n"); + printf("No need to regenerate ninja file\n"); return 0; } if (g_flags.dump_kati_stamp) { @@ -134,14 +133,9 @@ static int Run(const vector<Symbol>& targets, ClearGlobCache(); } - SetAffinityForSingleThread(); - MakefileCacheManager* cache_mgr = NewMakefileCacheManager(); Vars* vars = new Vars(); - vars->Assign(Intern("MAKEFILE_LIST"), - new SimpleVar(StringPrintf(" %s", g_flags.makefile), - VarOrigin::FILE)); for (char** p = environ; *p; p++) { SetVar(*p, VarOrigin::ENVIRONMENT, vars); } @@ -160,6 +154,10 @@ static int Run(const vector<Symbol>& targets, SetVar(l, VarOrigin::COMMAND_LINE, ev->mutable_vars()); } + vars->Assign(Intern("MAKEFILE_LIST"), + new SimpleVar(StringPrintf(" %s", g_flags.makefile), + VarOrigin::FILE)); + { ScopedTimeReporter tr("eval time"); Makefile* mk = cache_mgr->ReadMakefile(g_flags.makefile); @@ -210,8 +208,6 @@ static int Run(const vector<Symbol>& targets, for (Stmt* stmt : bootstrap_asts) delete stmt; delete ev; - // Each Var will be deleted by |ev|. - vars->clear(); delete vars; delete cache_mgr; @@ -16,22 +16,22 @@ #include "log.h" -Mutex::Mutex() { +mutex::mutex() { if (pthread_mutex_init(&mu_, NULL) != 0) PERROR("pthread_mutex_init"); } -Mutex::~Mutex() { +mutex::~mutex() { if (pthread_mutex_destroy(&mu_) != 0) PERROR("pthread_mutex_destroy"); } -void Mutex::lock() { +void mutex::lock() { if (pthread_mutex_lock(&mu_) != 0) PERROR("pthread_mutex_lock"); } -void Mutex::unlock() { +void mutex::unlock() { if (pthread_mutex_unlock(&mu_) != 0) PERROR("pthread_mutex_unlock"); } @@ -17,10 +17,10 @@ #include <pthread.h> -class Mutex { +class mutex { public: - explicit Mutex(); - ~Mutex(); + explicit mutex(); + ~mutex(); void lock(); void unlock(); @@ -31,17 +31,17 @@ class Mutex { friend class condition_variable; }; -template<class T> class UniqueLock { +template<class T> class unique_lock { public: - explicit UniqueLock(T& mu) + explicit unique_lock(T& mu) : mu_(mu) { mu_.lock(); } - ~UniqueLock() { + ~unique_lock() { mu_.unlock(); } - T* Mutex() const { return &mu_; } + T* mutex() const { return &mu_; } private: T& mu_; @@ -22,7 +22,6 @@ #include <unistd.h> #include <map> -#include <sstream> #include <string> #include <unordered_map> #include <unordered_set> @@ -41,8 +40,6 @@ #include "string_piece.h" #include "stringprintf.h" #include "strutil.h" -#include "thread_pool.h" -#include "timeutil.h" #include "var.h" #include "version.h" @@ -168,12 +165,6 @@ bool GetDepfileFromCommand(string* cmd, string* out) { return true; } -struct NinjaNode { - const DepNode* node; - vector<Command*> commands; - int rule_id; -}; - class NinjaGenerator { public: NinjaGenerator(Evaluator* ev, double start_time) @@ -184,7 +175,7 @@ class NinjaGenerator { start_time_(start_time), default_target_(NULL) { ev_->set_avoid_io(true); - shell_ = EscapeNinja(ev->EvalVar(kShellSym)); + shell_ = ev->EvalVar(kShellSym); if (g_flags.goma_dir) gomacc_ = StringPrintf("%s/gomacc ", g_flags.goma_dir); @@ -193,15 +184,12 @@ class NinjaGenerator { ~NinjaGenerator() { ev_->set_avoid_io(false); - for (NinjaNode* nn : nodes_) - delete nn; } void Generate(const vector<DepNode*>& nodes, const string& orig_args) { unlink(GetNinjaStampFilename().c_str()); - PopulateNinjaNodes(nodes); - GenerateNinja(orig_args); + GenerateNinja(nodes, orig_args); GenerateShell(); GenerateStamp(orig_args); } @@ -218,40 +206,8 @@ class NinjaGenerator { } private: - void PopulateNinjaNodes(const vector<DepNode*>& nodes) { - ScopedTimeReporter tr("ninja gen (eval)"); - for (DepNode* node : nodes) { - PopulateNinjaNode(node); - } - } - - void PopulateNinjaNode(DepNode* node) { - auto p = done_.insert(node->output); - if (!p.second) - return; - - // A hack to exclude out phony target in Android. If this exists, - // "ninja -t clean" tries to remove this directory and fails. - if (g_flags.detect_android_echo && node->output.str() == "out") - return; - - // This node is a leaf node - if (!node->has_rule && !node->is_phony) { - return; - } - - NinjaNode* nn = new NinjaNode; - nn->node = node; - ce_.Eval(node, &nn->commands); - nn->rule_id = nn->commands.empty() ? -1 : rule_id_++; - nodes_.push_back(nn); - - for (DepNode* d : node->deps) { - PopulateNinjaNode(d); - } - for (DepNode* d : node->order_onlys) { - PopulateNinjaNode(d); - } + string GenRuleName() { + return StringPrintf("rule%d", rule_id_++); } StringPiece TranslateCommand(const char* in, string* cmd_buf) { @@ -328,22 +284,6 @@ class NinjaGenerator { cmd_buf->size() - orig_size); } - bool IsOutputMkdir(const char *name, StringPiece cmd) { - if (!HasPrefix(cmd, "mkdir -p ")) { - return false; - } - cmd = cmd.substr(9, cmd.size()); - if (cmd.get(cmd.size() - 1) == '/') { - cmd = cmd.substr(0, cmd.size() - 1); - } - - StringPiece dir = Dirname(name); - if (cmd == dir) { - return true; - } - return false; - } - bool GetDescriptionFromCommand(StringPiece cmd, string *out) { if (!HasPrefix(cmd, "echo ")) { return false; @@ -393,8 +333,7 @@ class NinjaGenerator { return true; } - bool GenShellScript(const char *name, - const vector<Command*>& commands, + bool GenShellScript(const vector<Command*>& commands, string* cmd_buf, string* description) { // TODO: This is a dirty hack to set local_pool even without @@ -408,10 +347,7 @@ class NinjaGenerator { bool got_descritpion = false; bool use_gomacc = false; bool should_ignore_error = false; - auto command_count = commands.size(); for (const Command* c : commands) { - size_t cmd_begin = cmd_buf->size(); - if (!cmd_buf->empty()) { if (should_ignore_error) { *cmd_buf += " ; "; @@ -425,7 +361,7 @@ class NinjaGenerator { while (isspace(*in)) in++; - bool needs_subshell = command_count > 1; + bool needs_subshell = commands.size() > 1; if (*in == '(') { needs_subshell = false; } @@ -438,15 +374,11 @@ class NinjaGenerator { if (g_flags.detect_android_echo && !got_descritpion && !c->echo && GetDescriptionFromCommand(translated, description)) { got_descritpion = true; - translated.clear(); - } else if (IsOutputMkdir(name, translated) && !c->echo && - cmd_begin == 0) { + cmd_buf->resize(cmd_start); translated.clear(); } if (translated.empty()) { - cmd_buf->resize(cmd_begin); - command_count -= 1; - continue; + *cmd_buf += "true"; } else if (g_flags.goma_dir) { size_t pos = GetGomaccPosForAndroidCompileCommand(translated); if (pos != string::npos) { @@ -469,7 +401,7 @@ class NinjaGenerator { g_flags.goma_dir) && !use_gomacc; } - bool GetDepfile(const DepNode* node, string* cmd_buf, string* depfile) { + bool GetDepfile(DepNode* node, string* cmd_buf, string* depfile) { if (node->depfile_var) { node->depfile_var->Eval(ev_, depfile); return true; @@ -481,55 +413,75 @@ class NinjaGenerator { return result; } - void EmitDepfile(NinjaNode* nn, string* cmd_buf, ostringstream* o) { - const DepNode* node = nn->node; + void EmitDepfile(DepNode* node, string* cmd_buf) { string depfile; if (!GetDepfile(node, cmd_buf, &depfile)) return; - *o << " depfile = " << depfile << "\n"; - *o << " deps = gcc\n"; + fprintf(fp_, " depfile = %s\n", depfile.c_str()); + fprintf(fp_, " deps = gcc\n"); } - void EmitNode(NinjaNode* nn, ostringstream* o) { - const DepNode* node = nn->node; - const vector<Command*>& commands = nn->commands; + void EmitNode(DepNode* node) { + auto p = done_.insert(node->output); + if (!p.second) + return; + + // A hack to exclude out phony target in Android. If this exists, + // "ninja -t clean" tries to remove this directory and fails. + if (g_flags.detect_android_echo && node->output.str() == "out") + return; + + // This node is a leaf node + if (!node->has_rule && !node->is_phony) { + return; + } + + vector<Command*> commands; + ce_.Eval(node, &commands); string rule_name = "phony"; bool use_local_pool = false; if (!commands.empty()) { - rule_name = StringPrintf("rule%d", nn->rule_id); - *o << "rule " << rule_name << "\n"; + rule_name = GenRuleName(); + fprintf(fp_, "rule %s\n", rule_name.c_str()); string description = "build $out"; string cmd_buf; - use_local_pool |= GenShellScript(node->output.c_str(), commands, - &cmd_buf, &description); - *o << " description = " << description << "\n"; - EmitDepfile(nn, &cmd_buf, o); + use_local_pool |= GenShellScript(commands, &cmd_buf, &description); + fprintf(fp_, " description = %s\n", description.c_str()); + EmitDepfile(node, &cmd_buf); // It seems Linux is OK with ~130kB and Mac's limit is ~250kB. // TODO: Find this number automatically. if (cmd_buf.size() > 100 * 1000) { - *o << " rspfile = $out.rsp\n"; - *o << " rspfile_content = " << cmd_buf << "\n"; - *o << " command = " << shell_ << " $out.rsp\n"; + fprintf(fp_, " rspfile = $out.rsp\n"); + fprintf(fp_, " rspfile_content = %s\n", cmd_buf.c_str()); + fprintf(fp_, " command = %s $out.rsp\n", shell_.c_str()); } else { EscapeShell(&cmd_buf); - *o << " command = " << shell_ << " -c \"" << cmd_buf << "\"\n"; + fprintf(fp_, " command = %s -c \"%s\"\n", + shell_.c_str(), cmd_buf.c_str()); } if (node->is_restat) { - *o << " restat = 1\n"; + fprintf(fp_, " restat = 1\n"); } } - EmitBuild(nn, rule_name, use_local_pool, o); + EmitBuild(node, rule_name, use_local_pool); + + for (DepNode* d : node->deps) { + EmitNode(d); + } + for (DepNode* d : node->order_onlys) { + EmitNode(d); + } } - string EscapeNinja(const string& s) const { - if (s.find_first_of("$: ") == string::npos) - return s; + string EscapeBuildTarget(Symbol s) const { + if (s.str().find_first_of("$: ") == string::npos) + return s.str(); string r; - for (char c : s) { + for (char c : s.str()) { switch (c) { case '$': case ':': @@ -543,33 +495,58 @@ class NinjaGenerator { return r; } - string EscapeBuildTarget(Symbol s) const { - return EscapeNinja(s.str()); + void EscapeShell(string* s) const { + if (s->find_first_of("$`\\\"") == string::npos) + return; + string r; + bool last_dollar = false; + for (char c : *s) { + switch (c) { + case '$': + if (last_dollar) { + r += c; + last_dollar = false; + } else { + r += '\\'; + r += c; + last_dollar = true; + } + break; + case '`': + case '"': + case '\\': + r += '\\'; + // fall through. + default: + r += c; + last_dollar = false; + } + } + s->swap(r); } - void EmitBuild(NinjaNode* nn, const string& rule_name, - bool use_local_pool, ostringstream* o) { - const DepNode* node = nn->node; + void EmitBuild(DepNode* node, const string& rule_name, bool use_local_pool) { string target = EscapeBuildTarget(node->output); - *o << "build " << target << ": " << rule_name; + fprintf(fp_, "build %s: %s", + target.c_str(), + rule_name.c_str()); vector<Symbol> order_onlys; if (node->is_phony) { - *o << " _kati_always_build_"; + fprintf(fp_, " _kati_always_build_"); } for (DepNode* d : node->deps) { - *o << " " << EscapeBuildTarget(d->output).c_str(); + fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str()); } if (!node->order_onlys.empty()) { - *o << " ||"; + fprintf(fp_, " ||"); for (DepNode* d : node->order_onlys) { - *o << " " << EscapeBuildTarget(d->output).c_str(); + fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str()); } } - *o << "\n"; + fprintf(fp_, "\n"); if (use_local_pool) - *o << " pool = local_pool\n"; + fprintf(fp_, " pool = local_pool\n"); if (node->is_default_target) { - UniqueLock<Mutex> lock(mu_); default_target_ = node; } } @@ -596,8 +573,8 @@ class NinjaGenerator { return GetFilename("env%s.sh"); } - void GenerateNinja(const string& orig_args) { - ScopedTimeReporter tr("ninja gen (emit)"); + void GenerateNinja(const vector<DepNode*>& nodes, + const string& orig_args) { fp_ = fopen(GetNinjaFilename().c_str(), "wb"); if (fp_ == NULL) PERROR("fopen(build.ninja) failed"); @@ -624,24 +601,8 @@ class NinjaGenerator { EmitRegenRules(orig_args); - unique_ptr<ThreadPool> tp(NewThreadPool(g_flags.num_jobs)); - CHECK(g_flags.num_jobs); - int num_nodes_per_task = nodes_.size() / (g_flags.num_jobs * 10) + 1; - int num_tasks = nodes_.size() / num_nodes_per_task + 1; - vector<ostringstream> bufs(num_tasks); - for (int i = 0; i < num_tasks; i++) { - tp->Submit([this, i, num_nodes_per_task, &bufs]() { - int l = min(num_nodes_per_task * (i + 1), - static_cast<int>(nodes_.size())); - for (int j = num_nodes_per_task * i; j < l; j++) { - EmitNode(nodes_[j], &bufs[i]); - } - }); - } - tp->Wait(); - - for (const ostringstream& buf : bufs) { - fprintf(fp_, "%s", buf.str().c_str()); + for (DepNode* node : nodes) { + EmitNode(node); } unordered_set<Symbol> used_env_vars(Vars::used_env_vars()); @@ -804,11 +765,8 @@ class NinjaGenerator { string shell_; map<string, string> used_envs_; string kati_binary_; - const double start_time_; - vector<NinjaNode*> nodes_; - - Mutex mu_; - const DepNode* default_target_; + double start_time_; + DepNode* default_target_; }; string GetNinjaFilename() { @@ -364,7 +364,7 @@ class StampChecker { // TODO: Make glob cache thread safe and create a task for each glob. for (GlobResult* gr : globs_) { if (CheckGlobResult(gr, &err)) { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); if (!needs_regen_) { needs_regen_ = true; msg_ = err; @@ -378,7 +378,7 @@ class StampChecker { tp->Submit([this, sr]() { string err; if (CheckShellResult(sr, &err)) { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); if (!needs_regen_) { needs_regen_ = true; msg_ = err; @@ -398,7 +398,7 @@ class StampChecker { double gen_time_; vector<GlobResult*> globs_; vector<ShellResult*> commands_; - Mutex mu_; + mutex mu_; bool needs_regen_; string msg_; }; diff --git a/run_integration_test.rb b/run_integration_test.rb new file mode 100755 index 0000000..3a5b7d0 --- /dev/null +++ b/run_integration_test.rb @@ -0,0 +1,182 @@ +#!/usr/bin/env ruby +# +# Copyright 2015 Google Inc. All rights reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'fileutils' + +FileUtils.mkdir_p('repo') +Dir.chdir('repo') + +def check_command(cmd) + puts cmd + if !system(cmd) + puts "#{cmd} failed" + exit 1 + end +end + +class TestCase + attr_reader :name + + def initialize(name, checkout, prepare, clean, target) + @name = name + @checkout = checkout + @prepare = prepare + @clean = clean + @target = target + end + + def normalize_log(log, out) + # TODO: Fix. + if @name == 'android' + log = log.gsub(/[ \t]+/, ' ') + log = log.split("\n").sort.join("\n").sub(/ Stop\.$/, '') + # This is a completely sane warning from kati for Android. + log.sub!(%r(build/core/product_config.mk:152: warning: Unmatched parens: .*\n), '') + # Not sure why the order can be inconsistent, but this would be OK. + # TODO: Inevestigate. + log.gsub!(/(\.mk\.PRODUCT_COPY_FILES := )(.*)/){$1 + $2.split.sort * ' '} + end + File.open(out, 'w') do |of| + of.print log + end + log + end + + def run + @checkout.call(self) + + Dir.chdir(@name) do + @prepare.call(self) + + [['make', 'make'], ['kati', '../../kati']].each do |n, cmd| + @clean.call(self) + print "Running #{n} for #{@name}..." + STDOUT.flush + started = Time.now + system("#{cmd} #{@target} > #{n}.log 2>&1") + elapsed = Time.now - started + puts " %.2f secs" % elapsed + end + + make_log = File.read('make.log') + kati_log = File.read('kati.log') + kati_log.gsub!(/^\*kati\*.*\n/, '') + + make_log = normalize_log(make_log, 'make-normalized.log') + kati_log = normalize_log(kati_log, 'kati-normalized.log') + if make_log == kati_log + puts "#{@name}: OK" + return true + else + puts "#{@name}: FAIL" + return false + end + end + end +end + +class GitTestCase < TestCase + def initialize(name, repo, rev, prepare, clean, target) + checkout = Proc.new{|tc| + if !File.exist?(@name) + check_command("git clone #{repo}") + end + Dir.chdir(@name) { + check_command("git checkout #{rev}") + } + } + + super(name, checkout, prepare, clean, target) + end +end + +class AndroidTestCase < TestCase + def initialize + name = 'android' + checkout = Proc.new{|tc| + FileUtils.mkdir_p(@name) + md5 = `md5sum android.tgz` + need_update = true + if File.exist?("#{@name}/STAMP") + stamp = File.read("#{@name}/STAMP") + if md5 == stamp + need_update = false + end + end + + if need_update + check_command("tar -xzf android.tgz") + File.open("#{@name}/STAMP.tmp", 'w') do |ofile| + ofile.print(md5) + end + File.rename("#{@name}/STAMP.tmp", "#{@name}/STAMP") + end + } + + super(name, checkout, DO_NOTHING, DO_NOTHING, 'dump-products') + end +end + +DO_NOTHING = Proc.new{|tc|} +MAKE_CLEAN = Proc.new{|tc| + check_command("make clean > /dev/null") +} +CONFIGURE = Proc.new{|tc| + check_command("./configure > /dev/null") +} + +TESTS = [ + GitTestCase.new('maloader', + 'https://github.com/shinh/maloader.git', + '5d125933bc6c141bed05c309c2dc0e14ada6f5c7', + DO_NOTHING, + MAKE_CLEAN, + ''), + GitTestCase.new('glog', + 'https://github.com/google/glog', + '1b0b08c8dda1659027677966b03a3ff3c488e549', + CONFIGURE, + MAKE_CLEAN, + ''), + AndroidTestCase.new(), +] + +fails = [] +TESTS.each do |tc| + if !ARGV.empty? + if !ARGV.include?(tc.name) + next + end + end + + if !tc.run + fails << tc.name + end +end + +puts + +if fails.empty? + puts "PASS!" +else + puts "=== Failures ===" + fails.each do |n| + puts n + end + puts + + puts "FAIL!" +end @@ -341,6 +341,7 @@ run_shell_test = proc do |sh| output = normalize_kati_log(output) if is_ninja_test output = normalize_ninja_log(output, sh) + output.gsub!(/No need to regenerate ninja file\n/, '') end File.open('out.make', 'w'){|ofile|ofile.print(expected)} File.open('out.kati', 'w'){|ofile|ofile.print(output)} @@ -27,37 +27,43 @@ namespace { -Mutex g_mu; +mutex g_mu; vector<Stats*>* g_stats; +#ifdef __linux__ +thread_local double g_start_time; +#define REF(x) x +#else DEFINE_THREAD_LOCAL(double, g_start_time); +#define REF(x) x.Ref() +#endif } // namespace Stats::Stats(const char* name) : name_(name), elapsed_(0), cnt_(0) { - UniqueLock<Mutex> lock(g_mu); + unique_lock<mutex> lock(g_mu); if (g_stats == NULL) g_stats = new vector<Stats*>; g_stats->push_back(this); } string Stats::String() const { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); return StringPrintf("%s: %f / %d", name_, elapsed_, cnt_); } void Stats::Start() { - CHECK(!TLS_REF(g_start_time)); - TLS_REF(g_start_time) = GetTime(); - UniqueLock<Mutex> lock(mu_); + CHECK(!REF(g_start_time)); + REF(g_start_time) = GetTime(); + unique_lock<mutex> lock(mu_); cnt_++; } double Stats::End() { - CHECK(TLS_REF(g_start_time)); - double e = GetTime() - TLS_REF(g_start_time); - TLS_REF(g_start_time) = 0; - UniqueLock<Mutex> lock(mu_); + CHECK(REF(g_start_time)); + double e = GetTime() - REF(g_start_time); + REF(g_start_time) = 0; + unique_lock<mutex> lock(mu_); elapsed_ += e; return e; } @@ -36,7 +36,7 @@ class Stats { const char* name_; double elapsed_; int cnt_; - mutable Mutex mu_; + mutable mutex mu_; }; class ScopedStatsRecorder { @@ -55,19 +55,6 @@ string AssignStmt::DebugString() const { opstr, dirstr, LOCF(loc())); } -Symbol AssignStmt::GetLhsSymbol(Evaluator* ev) const { - if (!lhs->IsLiteral()) { - string buf; - lhs->Eval(ev, &buf); - return Intern(buf); - } - - if (!lhs_sym_cache_.IsValid()) { - lhs_sym_cache_ = Intern(lhs->GetLiteralValueUnsafe()); - } - return lhs_sym_cache_; -} - string CommandStmt::DebugString() const { return StringPrintf("CommandStmt(%s, loc=%s:%d)", expr->DebugString().c_str(), LOCF(loc())); @@ -20,7 +20,6 @@ #include "loc.h" #include "string_piece.h" -#include "symtab.h" using namespace std; @@ -86,19 +85,11 @@ struct AssignStmt : public Stmt { AssignOp op; AssignDirective directive; - AssignStmt() - : lhs_sym_cache_(Symbol::IsUninitialized{}) { - } virtual ~AssignStmt(); virtual void Eval(Evaluator* ev) const; virtual string DebugString() const; - - Symbol GetLhsSymbol(Evaluator* ev) const; - - private: - mutable Symbol lhs_sym_cache_; }; struct CommandStmt : public Stmt { diff --git a/string_piece.cc b/string_piece.cc index d287616..78de4ed 100644 --- a/string_piece.cc +++ b/string_piece.cc @@ -21,7 +21,6 @@ #include <ctype.h> #include <limits.h> -#include <stdint.h> #include <algorithm> #include <ostream> @@ -33,15 +32,8 @@ typedef StringPiece::size_type size_type; bool operator==(const StringPiece& x, const StringPiece& y) { if (x.size() != y.size()) return false; - size_t len = x.size(); - if (len >= sizeof(uint64_t)) { - len -= sizeof(uint64_t); - uint64_t xt = *reinterpret_cast<const uint64_t*>(x.data() + len); - uint64_t yt = *reinterpret_cast<const uint64_t*>(y.data() + len); - if (xt != yt) - return false; - } - return StringPiece::wordmemcmp(x.data(), y.data(), len) == 0; + + return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; } void StringPiece::CopyToString(std::string* target) const { diff --git a/string_piece_test.cc b/string_piece_test.cc index 0434cbe..7b253a0 100644 --- a/string_piece_test.cc +++ b/string_piece_test.cc @@ -30,8 +30,4 @@ int main() { assert(sps.size() == 2); assert(sps.count(StringPiece("foo")) == 1); assert(sps.count(StringPiece("bar")) == 1); - - assert(StringPiece("hogefugahige") == StringPiece("hogefugahige")); - assert(StringPiece("hogefugahoge") != StringPiece("hogefugahige")); - assert(StringPiece("hogefugahige") != StringPiece("higefugahige")); } @@ -55,11 +55,11 @@ static int SkipUntilSSE42(const char* s, int len, WordScanner::Iterator& WordScanner::Iterator::operator++() { int len = static_cast<int>(in->size()); - for (s = i + 1; s < len; s++) { + for (s = i; s < len; s++) { if (!isSpace((*in)[s])) break; } - if (s >= len) { + if (s == len) { in = NULL; s = 0; i = 0; @@ -92,7 +92,7 @@ WordScanner::Iterator WordScanner::begin() const { Iterator iter; iter.in = &in_; iter.s = 0; - iter.i = -1; + iter.i = 0; ++iter; return iter; } @@ -423,30 +423,6 @@ size_t FindThreeOutsideParen(StringPiece s, char c1, char c2, char c3) { } size_t FindEndOfLine(StringPiece s, size_t e, size_t* lf_cnt) { -#ifdef __SSE4_2__ - static const char ranges[] = "\n\n\\\\"; - while (e < s.size()) { - e += SkipUntilSSE42(s.data() + e, s.size() - e, ranges, 4); - char c = s[e]; - if (c == '\\') { - if (s[e+1] == '\n') { - e += 2; - ++*lf_cnt; - } else if (s[e+1] == '\r' && s[e+2] == '\n') { - e += 3; - ++*lf_cnt; - } else if (s[e+1] == '\\') { - e += 2; - } else { - e++; - } - } else if (c == '\n') { - ++*lf_cnt; - return e; - } - } - return e; -#else bool prev_backslash = false; for (; e < s.size(); e++) { char c = s[e]; @@ -463,7 +439,6 @@ size_t FindEndOfLine(StringPiece s, size_t e, size_t* lf_cnt) { } } return e; -#endif } StringPiece TrimLeadingCurdir(StringPiece s) { @@ -521,33 +496,3 @@ string EchoEscape(const string str) { } return buf; } - -void EscapeShell(string* s) { - if (s->find_first_of("$`\\\"") == string::npos) - return; - string r; - bool last_dollar = false; - for (char c : *s) { - switch (c) { - case '$': - if (last_dollar) { - r += c; - last_dollar = false; - } else { - r += '\\'; - r += c; - last_dollar = true; - } - break; - case '`': - case '"': - case '\\': - r += '\\'; - // fall through. - default: - r += c; - last_dollar = false; - } - } - s->swap(r); -} @@ -142,6 +142,4 @@ string ConcatDir(StringPiece b, StringPiece n); string EchoEscape(const string str); -void EscapeShell(string* s); - #endif // STRUTIL_H_ @@ -14,13 +14,8 @@ // +build ignore -//#define ENABLE_TID_CHECK - #include "symtab.h" -#ifdef ENABLE_TID_CHECK -#include <pthread.h> -#endif #include <string.h> #include <unordered_map> @@ -40,10 +35,6 @@ Symbol::Symbol(int v) class Symtab { public: Symtab() { -#ifdef ENABLE_TID_CHECK - tid_ = pthread_self(); -#endif - CHECK(g_symbols == NULL); g_symbols = &symbols_; @@ -81,11 +72,6 @@ class Symtab { } Symbol Intern(StringPiece s) { -#ifdef ENABLE_TID_CHECK - if (tid_ != pthread_self()) - abort(); -#endif - if (s.size() <= 1) { return Symbol(s.empty() ? 0 : (unsigned char)s[0]); } @@ -95,9 +81,6 @@ class Symtab { private: unordered_map<StringPiece, Symbol> symtab_; vector<string*> symbols_; -#ifdef ENABLE_TID_CHECK - pthread_t tid_; -#endif }; static Symtab* g_symtab; diff --git a/testcase/ninja_mkdir.sh b/testcase/ninja_mkdir.sh deleted file mode 100644 index e54298d..0000000 --- a/testcase/ninja_mkdir.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# Copyright 2016 Google Inc. All rights reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http:#www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -e - -log=/tmp/log -mk="$@" - -cat <<EOF > Makefile -test: a/b - -a/b: - @mkdir -p \$(dir \$@) - touch \$@ -EOF - -${mk} 2> ${log} -if [ -e ninja.sh ]; then - ./ninja.sh -fi -if [[ ! -d a ]]; then - echo "Created 'a'" -fi -if [ -e ninja.sh ]; then - if grep -q "mkdir -p" build.ninja; then - echo "Should not include 'mkdir -p' in build.ninja" - echo "Ninja will automatically create this directory" - fi -fi diff --git a/testcase/shell_var_with_args.mk b/testcase/shell_var_with_args.mk deleted file mode 100644 index ca7b54a..0000000 --- a/testcase/shell_var_with_args.mk +++ /dev/null @@ -1,9 +0,0 @@ -# TODO(go): Fix - -export FOO=-x - -SHELL := PS4="cmd: " /bin/bash $${FOO} -$(info $(shell echo foo)) - -test: - @echo baz diff --git a/testcase/sort.mk b/testcase/sort.mk index bf67a14..c521289 100644 --- a/testcase/sort.mk +++ b/testcase/sort.mk @@ -1,12 +1,5 @@ -sp := $(subst S, ,S) - test: echo $(sort foo bar lose) echo $(sort foo bar aaaa) echo $(sort foo bar lose lose foo bar bar) - echo $(sort baz bar) - echo $(sort single) - echo $(sort $(sp)foo$(sp)) echo $(sort ) - echo $(sort device/sample/products/AndroidProducts.mk device/moto/shamu/AndroidProducts.mk device/asus/fugu/AndroidProducts.mk device/asus/deb/AndroidProducts.mk device/asus/flo/AndroidProducts.mk device/generic/arm64/AndroidProducts.mk device/generic/qemu/AndroidProducts.mk device/generic/mini-emulator-x86_64/AndroidProducts.mk device/generic/x86/AndroidProducts.mk device/generic/mips/AndroidProducts.mk device/generic/mini-emulator-x86/AndroidProducts.mk device/generic/mini-emulator-mips/AndroidProducts.mk device/generic/mini-emulator-arm64/AndroidProducts.mk device/generic/mini-emulator-armv7-a-neon/AndroidProducts.mk device/generic/x86_64/AndroidProducts.mk device/generic/armv7-a-neon/AndroidProducts.mk device/htc/flounder/AndroidProducts.mk device/lge/bullhead/AndroidProducts.mk device/lge/hammerhead/AndroidProducts.mk device/huawei/angler/AndroidProducts.mk) - echo $(sort cpplint-art-phony libart libartd libgabi++ libopenjdkjvm libopenjdkjvmd libart) diff --git a/thread_local.h b/thread_local.h index 28b146a..3bbf663 100644 --- a/thread_local.h +++ b/thread_local.h @@ -39,13 +39,6 @@ #include "log.h" -#ifdef __linux__ - -#define DEFINE_THREAD_LOCAL(Type, name) thread_local Type name -#define TLS_REF(x) x - -#else - // Thread local storage implementation which uses pthread. // Note that DEFINE_THREAD_LOCAL creates a global variable just like // thread local storage based on __thread keyword. So we should not use @@ -95,8 +88,4 @@ class ThreadLocal { } \ ThreadLocal<Type, &name##_key, &name##_once> name; -#define TLS_REF(x) x.Ref() - -#endif - #endif // THREAD_LOCAL_H_ diff --git a/thread_pool.cc b/thread_pool.cc index c504ef5..ba7ee00 100644 --- a/thread_pool.cc +++ b/thread_pool.cc @@ -17,7 +17,6 @@ #include <stack> #include <vector> -#include "affinity.h" #include "condvar.h" #include "mutex.h" #include "thread.h" @@ -26,7 +25,6 @@ class ThreadPoolImpl : public ThreadPool { public: explicit ThreadPoolImpl(int num_threads) : is_waiting_(false) { - SetAffinityForMultiThread(); threads_.reserve(num_threads); for (int i = 0; i < num_threads; i++) { threads_.push_back(thread([this]() { Loop(); })); @@ -37,14 +35,14 @@ class ThreadPoolImpl : public ThreadPool { } virtual void Submit(function<void(void)> task) override { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); tasks_.push(task); cond_.notify_one(); } virtual void Wait() override { { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); is_waiting_ = true; cond_.notify_all(); } @@ -52,8 +50,6 @@ class ThreadPoolImpl : public ThreadPool { for (thread& th : threads_) { th.join(); } - - SetAffinityForSingleThread(); } private: @@ -61,7 +57,7 @@ class ThreadPoolImpl : public ThreadPool { while (true) { function<void(void)> task; { - UniqueLock<Mutex> lock(mu_); + unique_lock<mutex> lock(mu_); if (tasks_.empty()) { if (is_waiting_) return; @@ -79,7 +75,7 @@ class ThreadPoolImpl : public ThreadPool { } vector<thread> threads_; - Mutex mu_; + mutex mu_; condition_variable cond_; stack<function<void(void)>> tasks_; bool is_waiting_; @@ -47,10 +47,6 @@ void Var::AppendVar(Evaluator*, Value*) { CHECK(false); } -SimpleVar::SimpleVar(VarOrigin origin) - : origin_(origin) { -} - SimpleVar::SimpleVar(const string& v, VarOrigin origin) : v_(v), origin_(origin) { } @@ -125,7 +121,7 @@ Var* Vars::Lookup(Symbol name) const { } void Vars::Assign(Symbol name, Var* v) { - auto p = emplace(name, v); + auto p = insert(make_pair(name, v)); if (!p.second) { Var* orig = p.first->second; if (orig->Origin() == VarOrigin::OVERRIDE || @@ -145,7 +141,7 @@ unordered_set<Symbol> Vars::used_env_vars_; ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var) : vars_(vars), orig_(NULL) { - auto p = vars->emplace(name, var); + auto p = vars->insert(make_pair(name, var)); iter_ = p.first; if (!p.second) { orig_ = iter_->second; @@ -62,26 +62,23 @@ class Var : public Evaluable { class SimpleVar : public Var { public: - explicit SimpleVar(VarOrigin origin); SimpleVar(const string& v, VarOrigin origin); - virtual const char* Flavor() const override { + virtual const char* Flavor() const { return "simple"; } - virtual VarOrigin Origin() const override { + virtual VarOrigin Origin() const { return origin_; } virtual void Eval(Evaluator* ev, string* s) const override; - virtual void AppendVar(Evaluator* ev, Value* v) override; + virtual void AppendVar(Evaluator* ev, Value* v); virtual StringPiece String() const override; virtual string DebugString() const override; - string* mutable_value() { return &v_; } - private: string v_; VarOrigin origin_; @@ -91,16 +88,16 @@ class RecursiveVar : public Var { public: RecursiveVar(Value* v, VarOrigin origin, StringPiece orig); - virtual const char* Flavor() const override { + virtual const char* Flavor() const { return "recursive"; } - virtual VarOrigin Origin() const override { + virtual VarOrigin Origin() const { return origin_; } virtual void Eval(Evaluator* ev, string* s) const override; - virtual void AppendVar(Evaluator* ev, Value* v) override; + virtual void AppendVar(Evaluator* ev, Value* v); virtual StringPiece String() const override; @@ -116,13 +113,13 @@ class UndefinedVar : public Var { public: UndefinedVar(); - virtual const char* Flavor() const override { + virtual const char* Flavor() const { return "undefined"; } - virtual VarOrigin Origin() const override { + virtual VarOrigin Origin() const { return VarOrigin::UNDEFINED; } - virtual bool IsDefined() const override { return false; } + virtual bool IsDefined() const { return false; } virtual void Eval(Evaluator* ev, string* s) const override; @@ -141,19 +138,19 @@ class RuleVar : public Var { delete v_; } - virtual const char* Flavor() const override { + virtual const char* Flavor() const { return v_->Flavor(); } - virtual VarOrigin Origin() const override { + virtual VarOrigin Origin() const { return v_->Origin(); } - virtual bool IsDefined() const override { + virtual bool IsDefined() const { return v_->IsDefined(); } - virtual void Eval(Evaluator* ev, string* s) const override { + virtual void Eval(Evaluator* ev, string* s) const { v_->Eval(ev, s); } - virtual void AppendVar(Evaluator* ev, Value* v) override { + virtual void AppendVar(Evaluator* ev, Value* v) { v_->AppendVar(ev, v); } virtual StringPiece String() const override { |