Create separate Android.mk for main build targets

The runtime, compiler, dex2oat, and oatdump now are in seperate trees
to prevent dependency creep.  They can now be individually built
without rebuilding the rest of the art projects. dalvikvm and jdwpspy
were already this way. Builds in the art directory should behave as
before, building everything including tests.

Change-Id: Ic6b1151e5ed0f823c3dd301afd2b13eb2d8feb81
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/sea.cc
new file mode 100644
index 0000000..95c36e5
--- /dev/null
+++ b/compiler/sea_ir/sea.cc
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 "sea.h"
+
+#include "file_output_stream.h"
+
+#define MAX_REACHING_DEF_ITERERATIONS (10)
+
+namespace sea_ir {
+
+SeaGraph SeaGraph::graph_;
+int SeaNode::current_max_node_id_ = 0;
+
+
+SeaGraph* SeaGraph::GetCurrentGraph() {
+  return &sea_ir::SeaGraph::graph_;
+}
+
+void SeaGraph::DumpSea(std::string filename) const {
+  std::string result;
+  result += "digraph seaOfNodes {\n";
+  for (std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
+    (*cit)->ToDot(result);
+  }
+  result += "}\n";
+  art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
+  art::FileOutputStream fos(file);
+  fos.WriteFully(result.c_str(), result.size());
+  LOG(INFO) << "Written SEA string to file.";
+}
+
+void SeaGraph::AddEdge(Region* src, Region* dst) const {
+  src->AddSuccessor(dst);
+  dst->AddPredecessor(src);
+}
+
+void SeaGraph::ComputeDownExposedDefs() {
+  for (std::vector<Region*>::iterator region_it = regions_.begin();
+        region_it != regions_.end(); region_it++) {
+      (*region_it)->ComputeDownExposedDefs();
+    }
+}
+
+void SeaGraph::ComputeReachingDefs() {
+  // Iterate until the reaching definitions set doesn't change anymore.
+  // (See Cooper & Torczon, "Engineering a Compiler", second edition, page 487)
+  bool changed = true;
+  int iteration = 0;
+  while (changed && (iteration < MAX_REACHING_DEF_ITERERATIONS)) {
+    iteration++;
+    changed = false;
+    // TODO: optimize the ordering if this becomes performance bottleneck.
+    for (std::vector<Region*>::iterator regions_it = regions_.begin();
+        regions_it != regions_.end();
+        regions_it++) {
+      changed |= (*regions_it)->UpdateReachingDefs();
+    }
+  }
+  DCHECK(!changed) << "Reaching definitions computation did not reach a fixed point.";
+}
+
+
+void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item,
+  uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file) {
+  const uint16_t* code = code_item->insns_;
+  const size_t size_in_code_units = code_item->insns_size_in_code_units_;
+
+  Region* r = NULL;
+  // This maps  target instruction pointers to their corresponding region objects.
+  std::map<const uint16_t*, Region*> target_regions;
+  size_t i = 0;
+
+  // Pass: Find the start instruction of basic blocks
+  //         by locating targets and flow-though instructions of branches.
+  while (i < size_in_code_units) {
+    const art::Instruction* inst = art::Instruction::At(&code[i]);
+    if (inst->IsBranch()||inst->IsUnconditional()) {
+      int32_t offset = inst->GetTargetOffset();
+      if (target_regions.end() == target_regions.find(&code[i+offset])) {
+        Region* region = GetNewRegion();
+        target_regions.insert(std::pair<const uint16_t*, Region*>(&code[i+offset], region));
+      }
+      if (inst->CanFlowThrough() &&
+          (target_regions.end() == target_regions.find(&code[i+inst->SizeInCodeUnits()]))) {
+        Region* region = GetNewRegion();
+        target_regions.insert(std::pair<const uint16_t*, Region*>(&code[i+inst->SizeInCodeUnits()], region));
+      }
+    }
+    i += inst->SizeInCodeUnits();
+  }
+
+  // Pass: Assign instructions to region nodes and
+  //         assign branches their control flow successors.
+  i = 0;
+  r = GetNewRegion();
+  sea_ir::InstructionNode* last_node = NULL;
+  sea_ir::InstructionNode* node = NULL;
+  while (i < size_in_code_units) {
+    const art::Instruction* inst = art::Instruction::At(&code[i]); //TODO: find workaround for this
+    last_node = node;
+    node = new sea_ir::InstructionNode(inst);
+
+    if (inst->IsBranch() || inst->IsUnconditional()) {
+      int32_t offset = inst->GetTargetOffset();
+      std::map<const uint16_t*, Region*>::iterator it = target_regions.find(&code[i+offset]);
+      DCHECK(it != target_regions.end());
+      AddEdge(r, it->second); // Add edge to branch target.
+    }
+
+    std::map<const uint16_t*, Region*>::iterator it = target_regions.find(&code[i]);
+    if (target_regions.end() != it) {
+      // Get the already created region because this is a branch target.
+      Region* nextRegion = it->second;
+      if (last_node->GetInstruction()->IsBranch() && last_node->GetInstruction()->CanFlowThrough()) {
+        AddEdge(r, it->second); // Add flow-through edge.
+      }
+      r = nextRegion;
+    }
+    bool definesRegister = (0 !=
+            InstructionTools::instruction_attributes_[inst->Opcode()] && (1 << kDA));
+    LOG(INFO) << inst->GetDexPc(code) << "*** " << inst->DumpString(&dex_file)
+            << " region:" <<r->StringId() << "Definition?" << definesRegister << std::endl;
+    r->AddChild(node);
+    i += inst->SizeInCodeUnits();
+  }
+
+  // Pass: compute downward-exposed definitions.
+  ComputeDownExposedDefs();
+
+  // Multiple Passes: Compute reaching definitions (iterative fixed-point algorithm)
+  ComputeReachingDefs();
+}
+
+Region* SeaGraph::GetNewRegion() {
+  Region* new_region = new Region();
+  AddRegion(new_region);
+  return new_region;
+}
+
+void SeaGraph::AddRegion(Region* r) {
+  DCHECK(r) << "Tried to add NULL region to SEA graph.";
+  regions_.push_back(r);
+}
+
+void Region::AddChild(sea_ir::InstructionNode* instruction) {
+  DCHECK(instruction) << "Tried to add NULL instruction to region node.";
+  instructions_.push_back(instruction);
+}
+
+SeaNode* Region::GetLastChild() const {
+  if (instructions_.size() > 0) {
+    return instructions_.back();
+  }
+  return NULL;
+}
+
+void InstructionNode::ToDot(std::string& result) const {
+  result += "// Instruction: \n" + StringId() +
+      " [label=\"" + instruction_->DumpString(NULL) + "\"";
+  if (de_def_) {
+    result += "style=bold";
+  }
+  result += "];\n";
+}
+
+int InstructionNode::GetResultRegister() const {
+  if (!InstructionTools::IsDefinition(instruction_)) {
+    return NO_REGISTER;
+  }
+  return instruction_->VRegA();
+}
+
+void InstructionNode::MarkAsDEDef() {
+  de_def_ = true;
+}
+
+void Region::ToDot(std::string& result) const {
+  result += "\n// Region: \n" + StringId() + " [label=\"region " + StringId() + "\"];";
+  // Save instruction nodes that belong to this region.
+  for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
+      cit != instructions_.end(); cit++) {
+    (*cit)->ToDot(result);
+    result += StringId() + " -> " + (*cit)->StringId() + ";\n";
+  }
+
+  for (std::vector<Region*>::const_iterator cit = successors_.begin(); cit != successors_.end();
+      cit++) {
+    DCHECK(NULL != *cit) << "Null successor found for SeaNode" << GetLastChild()->StringId() << ".";
+    result += GetLastChild()->StringId() + " -> " + (*cit)->StringId() + ";\n\n";
+  }
+
+  // Save reaching definitions.
+  for (std::map<int, std::set<sea_ir::InstructionNode*>* >::const_iterator cit =
+      reaching_defs_.begin();
+      cit != reaching_defs_.end(); cit++) {
+    for (std::set<sea_ir::InstructionNode*>::const_iterator
+        reaching_set_it = (*cit).second->begin();
+        reaching_set_it != (*cit).second->end();
+        reaching_set_it++) {
+      result += (*reaching_set_it)->StringId() +
+         " -> " + StringId() +
+         " [style=dotted]; // Reaching def.\n";
+    }
+  }
+
+  result += "// End Region.\n";
+}
+
+
+void Region::ComputeDownExposedDefs() {
+  for (std::vector<InstructionNode*>::const_iterator inst_it = instructions_.begin();
+      inst_it != instructions_.end(); inst_it++) {
+    int reg_no = (*inst_it)->GetResultRegister();
+    std::map<int, InstructionNode*>::iterator res = de_defs_.find(reg_no);
+    if ((reg_no != NO_REGISTER) && (res == de_defs_.end())) {
+      de_defs_.insert(std::pair<int, InstructionNode*>(reg_no, *inst_it));
+    } else {
+      res->second = *inst_it;
+    }
+  }
+
+  for (std::map<int, sea_ir::InstructionNode*>::const_iterator cit = de_defs_.begin();
+      cit != de_defs_.end(); cit++) {
+    (*cit).second->MarkAsDEDef();
+  }
+}
+
+
+const std::map<int, sea_ir::InstructionNode*>* Region::GetDownExposedDefs() const {
+  return &de_defs_;
+}
+
+std::map<int, std::set<sea_ir::InstructionNode*>* >* Region::GetReachingDefs() {
+  return &reaching_defs_;
+}
+
+bool Region::UpdateReachingDefs() {
+  std::map<int, std::set<sea_ir::InstructionNode*>* > new_reaching;
+  for (std::vector<Region*>::const_iterator pred_it = predecessors_.begin();
+      pred_it != predecessors_.end(); pred_it++) {
+    // The reaching_defs variable will contain reaching defs __for current predecessor only__
+    std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs;
+    std::map<int, std::set<sea_ir::InstructionNode*>* >* pred_reaching = (*pred_it)->GetReachingDefs();
+    const std::map<int, InstructionNode*>* de_defs = (*pred_it)->GetDownExposedDefs();
+
+    // The definitions from the reaching set of the predecessor
+    // may be shadowed by downward exposed definitions from the predecessor,
+    // otherwise the defs from the reaching set are still good.
+    for (std::map<int, InstructionNode*>::const_iterator de_def = de_defs->begin();
+        de_def != de_defs->end(); de_def++) {
+      std::set<InstructionNode*>* solo_def;
+      solo_def = new std::set<InstructionNode*>();
+      solo_def->insert(de_def->second);
+      reaching_defs.insert(
+          std::pair<int const, std::set<InstructionNode*>*>(de_def->first, solo_def));
+    }
+    LOG(INFO) << "Adding to " <<StringId() << "reaching set of " << (*pred_it)->StringId();
+    reaching_defs.insert(pred_reaching->begin(), pred_reaching->end());
+
+    // Now we combine the reaching map coming from the current predecessor (reaching_defs)
+    // with the accumulated set from all predecessors so far (from new_reaching).
+    std::map<int, std::set<sea_ir::InstructionNode*>*>::iterator reaching_it = reaching_defs.begin();
+    for (; reaching_it != reaching_defs.end(); reaching_it++) {
+      std::map<int, std::set<sea_ir::InstructionNode*>*>::iterator crt_entry =
+          new_reaching.find(reaching_it->first);
+      if (new_reaching.end() != crt_entry) {
+        crt_entry->second->insert(reaching_it->second->begin(), reaching_it->second->end());
+      } else {
+        new_reaching.insert(
+            std::pair<int, std::set<sea_ir::InstructionNode*>*>(
+                reaching_it->first,
+                reaching_it->second) );
+      }
+    }
+  }
+  bool changed = false;
+  // Because the sets are monotonically increasing,
+  // we can compare sizes instead of using set comparison.
+  // TODO: Find formal proof.
+  int old_size = 0;
+  if (-1 == reaching_defs_size_) {
+    std::map<int, std::set<sea_ir::InstructionNode*>*>::iterator reaching_it = reaching_defs_.begin();
+    for (; reaching_it != reaching_defs_.end(); reaching_it++) {
+      old_size += (*reaching_it).second->size();
+    }
+  } else {
+    old_size = reaching_defs_size_;
+  }
+  int new_size = 0;
+  std::map<int, std::set<sea_ir::InstructionNode*>*>::iterator reaching_it = new_reaching.begin();
+  for (; reaching_it != new_reaching.end(); reaching_it++) {
+    new_size += (*reaching_it).second->size();
+  }
+  if (old_size != new_size) {
+    changed = true;
+  }
+  if (changed) {
+    reaching_defs_ = new_reaching;
+    reaching_defs_size_ = new_size;
+  }
+  return changed;
+}
+
+void SeaNode::AddSuccessor(Region* successor) {
+  DCHECK(successor) << "Tried to add NULL successor to SEA node.";
+  successors_.push_back(successor);
+  return;
+}
+
+void SeaNode::AddPredecessor(Region* predecessor) {
+  DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
+  predecessors_.push_back(predecessor);
+}
+
+} // end namespace sea_ir