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
diff --git a/Android.bp b/Android.bp
index fea1241..432505e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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_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
diff --git a/condvar.cc b/condvar.cc
index f8b488b..d7d4e39 100644
--- a/condvar.cc
+++ b/condvar.cc
@@ -26,8 +26,8 @@
     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");
 }
 
diff --git a/condvar.h b/condvar.h
index b75b9a4..2f9ab3a 100644
--- a/condvar.h
+++ b/condvar.h
@@ -24,7 +24,7 @@
   condition_variable();
   ~condition_variable();
 
-  void wait(const UniqueLock<Mutex>& mu);
+  void wait(const unique_lock<mutex>& mu);
   void notify_one();
   void notify_all();
 
diff --git a/dep.cc b/dep.cc
index 434d9ad..45f9584 100644
--- a/dep.cc
+++ b/dep.cc
@@ -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 @@
 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 @@
     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 @@
     }
   }
 
-  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 @@
                               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 @@
     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 @@
       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 @@
     }
   }
 
-  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 @@
 
   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 @@
 
     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 @@
 };
 
 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);
 }
 
diff --git a/dep.h b/dep.h
index 05d10d0..bb70eb3 100644
--- a/dep.h
+++ b/dep.h
@@ -15,6 +15,7 @@
 #ifndef DEP_H_
 #define DEP_H_
 
+#include <memory>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -52,7 +53,7 @@
 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);
diff --git a/eval.cc b/eval.cc
index be4bb34..ae41567 100644
--- a/eval.cc
+++ b/eval.cc
@@ -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* 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 @@
 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 @@
     }
 
     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 @@
     }
 
     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* 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;
 }
diff --git a/eval.h b/eval.h
index cb03d5d..6bc21b9 100644
--- a/eval.h
+++ b/eval.h
@@ -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 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 @@
   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 @@
 
   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_;
diff --git a/expr.cc b/expr.cc
index a629352..a8f306c 100644
--- a/expr.cc
+++ b/expr.cc
@@ -62,8 +62,7 @@
     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 @@
     return r;
   }
 
-  virtual Value* Compact() override {
+  virtual Value* Compact() {
     if (vals_.size() != 1) {
       return this;
     }
diff --git a/expr.h b/expr.h
index fdd6d36..e479ed8 100644
--- a/expr.h
+++ b/expr.h
@@ -42,8 +42,6 @@
   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 @@
 
   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 @@
 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 @@
       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);
diff --git a/find.cc b/find.cc
index b783acb..4c7cd8f 100644
--- a/find.cc
+++ b/find.cc
@@ -154,7 +154,7 @@
   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 @@
     }
   }
 
-  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 @@
   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 @@
       : 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 @@
   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_) {
diff --git a/flags.cc b/flags.cc
index 73c7105..06772f0 100644
--- a/flags.cc
+++ b/flags.cc
@@ -49,7 +49,7 @@
 
 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++) {
diff --git a/flags.h b/flags.h
index 275a3ee..d2fe923 100644
--- a/flags.h
+++ b/flags.h
@@ -44,7 +44,6 @@
   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;
diff --git a/func.cc b/func.cc
index 2ea8afa..39af0e9 100644
--- a/func.cc
+++ b/func.cc
@@ -182,14 +182,10 @@
 }
 
 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 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 @@
   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()));
     }
   }
 
diff --git a/main.cc b/main.cc
index c732dda..a64a37e 100644
--- a/main.cc
+++ b/main.cc
@@ -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 @@
   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 @@
     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 @@
     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 @@
   for (Stmt* stmt : bootstrap_asts)
     delete stmt;
   delete ev;
-  // Each Var will be deleted by |ev|.
-  vars->clear();
   delete vars;
   delete cache_mgr;
 
diff --git a/mutex.cc b/mutex.cc
index 986366b..ae4bd3b 100644
--- a/mutex.cc
+++ b/mutex.cc
@@ -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");
 }
diff --git a/mutex.h b/mutex.h
index e730294..d6f1f5a 100644
--- a/mutex.h
+++ b/mutex.h
@@ -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 @@
   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_;
diff --git a/ninja.cc b/ninja.cc
index eeefce0..f14610f 100644
--- a/ninja.cc
+++ b/ninja.cc
@@ -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 @@
   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 @@
         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 @@
 
   ~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 @@
   }
 
  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 @@
                        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 @@
     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 @@
     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 @@
       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 @@
       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 @@
             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 @@
     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 @@
     return r;
   }
 
-  string EscapeBuildTarget(Symbol s) const {
-    return EscapeNinja(s.str());
-  }
-
-  void EmitBuild(NinjaNode* nn, const string& rule_name,
-                 bool use_local_pool, ostringstream* o) {
-    const DepNode* node = nn->node;
-    string target = EscapeBuildTarget(node->output);
-    *o << "build " << target << ": " << rule_name;
-    vector<Symbol> order_onlys;
-    if (node->is_phony) {
-      *o << " _kati_always_build_";
-    }
-    for (DepNode* d : node->deps) {
-      *o << " " << EscapeBuildTarget(d->output).c_str();
-    }
-    if (!node->order_onlys.empty()) {
-      *o << " ||";
-      for (DepNode* d : node->order_onlys) {
-        *o << " " << EscapeBuildTarget(d->output).c_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;
       }
     }
-    *o << "\n";
+    s->swap(r);
+  }
+
+  void EmitBuild(DepNode* node, const string& rule_name, bool use_local_pool) {
+    string target = EscapeBuildTarget(node->output);
+    fprintf(fp_, "build %s: %s",
+            target.c_str(),
+            rule_name.c_str());
+    vector<Symbol> order_onlys;
+    if (node->is_phony) {
+      fprintf(fp_, " _kati_always_build_");
+    }
+    for (DepNode* d : node->deps) {
+      fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str());
+    }
+    if (!node->order_onlys.empty()) {
+      fprintf(fp_, " ||");
+      for (DepNode* d : node->order_onlys) {
+        fprintf(fp_, " %s", EscapeBuildTarget(d->output).c_str());
+      }
+    }
+    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 @@
     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 @@
 
     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 @@
   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() {
diff --git a/regen.cc b/regen.cc
index a448612..a40ebf3 100644
--- a/regen.cc
+++ b/regen.cc
@@ -364,7 +364,7 @@
         // 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 @@
       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 @@
   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
diff --git a/runtest.rb b/runtest.rb
index bf42bfe..7123113 100755
--- a/runtest.rb
+++ b/runtest.rb
@@ -341,6 +341,7 @@
     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)}
diff --git a/stats.cc b/stats.cc
index 60b3285..9d4a160 100644
--- a/stats.cc
+++ b/stats.cc
@@ -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;
 }
diff --git a/stats.h b/stats.h
index 190fa57..6244b54 100644
--- a/stats.h
+++ b/stats.h
@@ -36,7 +36,7 @@
   const char* name_;
   double elapsed_;
   int cnt_;
-  mutable Mutex mu_;
+  mutable mutex mu_;
 };
 
 class ScopedStatsRecorder {
diff --git a/stmt.cc b/stmt.cc
index 155e0cd..1abab32 100644
--- a/stmt.cc
+++ b/stmt.cc
@@ -55,19 +55,6 @@
                       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()));
diff --git a/stmt.h b/stmt.h
index 3b6feeb..4d4c5eb 100644
--- a/stmt.h
+++ b/stmt.h
@@ -20,7 +20,6 @@
 
 #include "loc.h"
 #include "string_piece.h"
-#include "symtab.h"
 
 using namespace std;
 
@@ -86,19 +85,11 @@
   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 @@
 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 @@
   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"));
 }
diff --git a/strutil.cc b/strutil.cc
index 80a4b5b..0e5e766 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -55,11 +55,11 @@
 
 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 @@
   Iterator iter;
   iter.in = &in_;
   iter.s = 0;
-  iter.i = -1;
+  iter.i = 0;
   ++iter;
   return iter;
 }
@@ -423,30 +423,6 @@
 }
 
 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 @@
     }
   }
   return e;
-#endif
 }
 
 StringPiece TrimLeadingCurdir(StringPiece s) {
@@ -521,33 +496,3 @@
   }
   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);
-}
diff --git a/strutil.h b/strutil.h
index 12e46a5..5938efb 100644
--- a/strutil.h
+++ b/strutil.h
@@ -142,6 +142,4 @@
 
 string EchoEscape(const string str);
 
-void EscapeShell(string* s);
-
 #endif  // STRUTIL_H_
diff --git a/symtab.cc b/symtab.cc
index af0b620..d8d7e93 100644
--- a/symtab.cc
+++ b/symtab.cc
@@ -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 @@
 class Symtab {
  public:
   Symtab() {
-#ifdef ENABLE_TID_CHECK
-    tid_ = pthread_self();
-#endif
-
     CHECK(g_symbols == NULL);
     g_symbols = &symbols_;
 
@@ -81,11 +72,6 @@
   }
 
   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 @@
  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 @@
   }                                                     \
   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 @@
  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 @@
   }
 
   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 @@
     for (thread& th : threads_) {
       th.join();
     }
-
-    SetAffinityForSingleThread();
   }
 
  private:
@@ -61,7 +57,7 @@
     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 @@
   }
 
   vector<thread> threads_;
-  Mutex mu_;
+  mutex mu_;
   condition_variable cond_;
   stack<function<void(void)>> tasks_;
   bool is_waiting_;
diff --git a/var.cc b/var.cc
index a5cde3e..d21dc4f 100644
--- a/var.cc
+++ b/var.cc
@@ -47,10 +47,6 @@
   CHECK(false);
 }
 
-SimpleVar::SimpleVar(VarOrigin origin)
-    : origin_(origin) {
-}
-
 SimpleVar::SimpleVar(const string& v, VarOrigin origin)
     : v_(v), origin_(origin) {
 }
@@ -125,7 +121,7 @@
 }
 
 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 @@
 
 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;
diff --git a/var.h b/var.h
index 5ba5fcb..3bae262 100644
--- a/var.h
+++ b/var.h
@@ -62,26 +62,23 @@
 
 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 @@
  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 @@
  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 @@
     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 {