Revert "ART: Implement try/catch blocks in Builder"

Causes OutOfMemory issues, need to investigate.

This reverts commit 0b5c7d1994b76090afcc825e737f2b8c546da2f8.

Change-Id: I263e6cc4df5f9a56ad2ce44e18932ca51d7e349f
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 742429c..e527e8b 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -259,165 +259,6 @@
   return false;
 }
 
-bool HGraphBuilder::IsBlockInPcRange(HBasicBlock* block,
-                                     uint32_t dex_pc_start,
-                                     uint32_t dex_pc_end) {
-  uint32_t dex_pc = block->GetDexPc();
-  return block != entry_block_
-      && block != exit_block_
-      && dex_pc >= dex_pc_start
-      && dex_pc < dex_pc_end;
-}
-
-void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) {
-  if (code_item.tries_size_ == 0) {
-    return;
-  }
-
-  // Create branch targets at the start/end of the TryItem range. These are
-  // places where the program might fall through into/out of the a block and
-  // where TryBoundary instructions will be inserted later. Other edges which
-  // enter/exit the try blocks are a result of branches/switches.
-  for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
-    const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
-    uint32_t dex_pc_start = try_item->start_addr_;
-    uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
-    FindOrCreateBlockStartingAt(dex_pc_start);
-    if (dex_pc_end < code_item.insns_size_in_code_units_) {
-      // TODO: Do not create block if the last instruction cannot fall through.
-      FindOrCreateBlockStartingAt(dex_pc_end);
-    } else {
-      // The TryItem spans until the very end of the CodeItem (or beyond if
-      // invalid) and therefore cannot have any code afterwards.
-    }
-  }
-
-  // Create branch targets for exception handlers.
-  const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
-  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
-  for (uint32_t idx = 0; idx < handlers_size; ++idx) {
-    CatchHandlerIterator iterator(handlers_ptr);
-    for (; iterator.HasNext(); iterator.Next()) {
-      uint32_t address = iterator.GetHandlerAddress();
-      HBasicBlock* block = FindOrCreateBlockStartingAt(address);
-      block->SetIsCatchBlock();
-    }
-    handlers_ptr = iterator.EndDataPointer();
-  }
-}
-
-void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) {
-  if (code_item.tries_size_ == 0) {
-    return;
-  }
-
-  for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
-    const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
-    uint32_t try_start = try_item->start_addr_;
-    uint32_t try_end = try_start + try_item->insn_count_;
-
-    // Iterate over all blocks in the dex pc range of the TryItem and:
-    //   (a) split edges which enter/exit the try range,
-    //   (b) create TryBoundary instructions in the new blocks,
-    //   (c) link the new blocks to corresponding exception handlers.
-    for (uint32_t inner_pc = try_start; inner_pc < try_end; ++inner_pc) {
-      HBasicBlock* try_block = FindBlockStartingAt(inner_pc);
-      if (try_block == nullptr) {
-        continue;
-      }
-
-      // Find predecessors which are not covered by the same TryItem range. Such
-      // edges enter the try block and will have a TryBoundary inserted.
-      for (size_t i = 0; i < try_block->GetPredecessors().Size(); ++i) {
-        HBasicBlock* predecessor = try_block->GetPredecessors().Get(i);
-        HTryBoundary* try_boundary = nullptr;
-        if (predecessor->IsSingleTryBoundary()) {
-          try_boundary = predecessor->GetLastInstruction()->AsTryBoundary();
-          if (try_boundary->GetNormalFlowSuccessor() == try_block
-              && try_block->IsFirstIndexOfPredecessor(predecessor, i)) {
-            // The edge was already split because of an exit from a neighbouring
-            // TryItem and `predecessor` is the block with a TryBoundary created
-            // between the two original blocks. We do not split the edge again.
-            DCHECK(!IsBlockInPcRange(predecessor->GetSinglePredecessor(), try_start, try_end));
-            DCHECK(try_boundary->IsTryExit());
-            DCHECK(!try_boundary->IsTryEntry());
-            try_boundary->SetIsTryEntry();
-          } else {
-            // This is an edge between a previously created TryBoundary and its
-            // handler. We skip it because it is exceptional flow.
-            DCHECK(try_block->IsCatchBlock());
-            DCHECK(try_boundary->HasExceptionHandler(try_block));
-            continue;
-          }
-        } else if (!IsBlockInPcRange(predecessor, try_start, try_end)) {
-          // This is an entry point into the TryItem and the edge has not been
-          // split yet. That means that either `predecessor` is not in a TryItem,
-          // or it is in a different TryItem and we happened to iterate over
-          // this block first. We split the edge and `predecessor` may add its
-          // own exception handlers later.
-          try_boundary = new (arena_) HTryBoundary(/* is_entry */ true, /* is_exit */ false);
-          HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, try_block);
-          try_entry_block->AddInstruction(try_boundary);
-        } else {
-          // Not an edge on the boundary of the try block.
-          continue;
-        }
-        DCHECK(try_boundary != nullptr);
-
-        // Link the TryBoundary block to the handlers of this TryItem.
-        for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
-          try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
-        }
-      }
-
-      // Find successors which are not covered by the same TryItem range. Such
-      // edges exit the try block and will have a TryBoundary inserted.
-      for (size_t i = 0; i < try_block->GetSuccessors().Size(); ++i) {
-        HBasicBlock* successor = try_block->GetSuccessors().Get(i);
-        HTryBoundary* try_boundary = nullptr;
-        if (successor->IsSingleTryBoundary()) {
-          // The edge was already split because of an entry into a neighbouring
-          // TryItem. We do not split the edge again.
-          try_boundary = successor->GetLastInstruction()->AsTryBoundary();
-          DCHECK_EQ(try_block, successor->GetSinglePredecessor());
-          DCHECK(try_boundary->IsTryEntry());
-          DCHECK(!try_boundary->IsTryExit());
-          DCHECK(!IsBlockInPcRange(try_boundary->GetNormalFlowSuccessor(), try_start, try_end));
-          try_boundary->SetIsTryExit();
-        } else if (!IsBlockInPcRange(successor, try_start, try_end)) {
-          // This is an exit out of the TryItem and the edge has not been split
-          // yet. That means that either `successor` is not in a TryItem, or it
-          // is in a different TryItem and we happened to iterate over this
-          // block first. We split the edge and `successor` may add its own
-          // exception handlers later.
-          HInstruction* last_instruction = try_block->GetLastInstruction();
-          if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) {
-            DCHECK_EQ(successor, exit_block_);
-            // Control flow exits the try block with a Return(Void). Because
-            // splitting the edge would invalidate the invariant that Return
-            // always jumps to Exit, we move the Return outside the try block.
-            HBasicBlock* return_block = try_block->SplitBefore(last_instruction);
-            graph_->AddBlock(return_block);
-            successor = return_block;
-          }
-          try_boundary = new (arena_) HTryBoundary(/* is_entry */ false, /* is_exit */ true);
-          HBasicBlock* try_exit_block = graph_->SplitEdge(try_block, successor);
-          try_exit_block->AddInstruction(try_boundary);
-        } else {
-          // Not an edge on the boundary of the try block.
-          continue;
-        }
-        DCHECK(try_boundary != nullptr);
-
-        // Link the TryBoundary block to the handlers of this TryItem.
-        for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
-          try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
-        }
-      }
-    }
-  }
-}
-
 bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
   DCHECK(graph_->GetBlocks().IsEmpty());
 
@@ -451,7 +292,24 @@
     return false;
   }
 
-  CreateBlocksForTryCatch(code_item);
+  // Also create blocks for catch handlers.
+  if (code_item.tries_size_ != 0) {
+    const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
+    uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
+    for (uint32_t idx = 0; idx < handlers_size; ++idx) {
+      CatchHandlerIterator iterator(handlers_ptr);
+      for (; iterator.HasNext(); iterator.Next()) {
+        uint32_t address = iterator.GetHandlerAddress();
+        HBasicBlock* block = FindBlockStartingAt(address);
+        if (block == nullptr) {
+          block = new (arena_) HBasicBlock(graph_, address);
+          branch_targets_.Put(address, block);
+        }
+        block->SetIsCatchBlock();
+      }
+      handlers_ptr = iterator.EndDataPointer();
+    }
+  }
 
   InitializeParameters(code_item.ins_size_);
 
@@ -467,24 +325,18 @@
     code_ptr += instruction.SizeInCodeUnits();
   }
 
+  // Add the exit block at the end to give it the highest id.
+  graph_->AddBlock(exit_block_);
+  exit_block_->AddInstruction(new (arena_) HExit());
   // Add the suspend check to the entry block.
   entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
   entry_block_->AddInstruction(new (arena_) HGoto());
-  // Add Exit to the exit block.
-  exit_block_->AddInstruction(new (arena_) HExit());
 
-  // Iterate over blocks covered by TryItems and insert TryBoundaries at entry
-  // and exit points. This requires all control-flow instructions and
-  // non-exceptional edges to have been created.
-  InsertTryBoundaryBlocks(code_item);
-
-  // Add the exit block at the end to give it the highest id.
-  graph_->AddBlock(exit_block_);
   return true;
 }
 
-void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) {
-  HBasicBlock* block = FindBlockStartingAt(dex_pc);
+void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
+  HBasicBlock* block = FindBlockStartingAt(index);
   if (block == nullptr) {
     return;
   }
@@ -519,8 +371,10 @@
       (*number_of_branches)++;
       int32_t target = instruction.GetTargetOffset() + dex_pc;
       // Create a block for the target instruction.
-      FindOrCreateBlockStartingAt(target);
-
+      if (FindBlockStartingAt(target) == nullptr) {
+        block = new (arena_) HBasicBlock(graph_, target);
+        branch_targets_.Put(target, block);
+      }
       dex_pc += instruction.SizeInCodeUnits();
       code_ptr += instruction.SizeInCodeUnits();
 
@@ -529,8 +383,9 @@
           // In the normal case we should never hit this but someone can artificially forge a dex
           // file to fall-through out the method code. In this case we bail out compilation.
           return false;
-        } else {
-          FindOrCreateBlockStartingAt(dex_pc);
+        } else if (FindBlockStartingAt(dex_pc) == nullptr) {
+          block = new (arena_) HBasicBlock(graph_, dex_pc);
+          branch_targets_.Put(dex_pc, block);
         }
       }
     } else if (instruction.IsSwitch()) {
@@ -546,7 +401,10 @@
       for (size_t i = 0; i < num_entries; ++i) {
         // The target of the case.
         uint32_t target = dex_pc + table.GetEntryAt(i + offset);
-        FindOrCreateBlockStartingAt(target);
+        if (FindBlockStartingAt(target) == nullptr) {
+          block = new (arena_) HBasicBlock(graph_, target);
+          branch_targets_.Put(target, block);
+        }
 
         // The next case gets its own block.
         if (i < num_entries) {
@@ -563,8 +421,9 @@
         // file to fall-through out the method code. In this case we bail out compilation.
         // (A switch can fall-through so we don't need to check CanFlowThrough().)
         return false;
-      } else {
-        FindOrCreateBlockStartingAt(dex_pc);
+      } else if (FindBlockStartingAt(dex_pc) == nullptr) {
+        block = new (arena_) HBasicBlock(graph_, dex_pc);
+        branch_targets_.Put(dex_pc, block);
       }
     } else {
       code_ptr += instruction.SizeInCodeUnits();
@@ -574,19 +433,9 @@
   return true;
 }
 
-HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const {
-  DCHECK_GE(dex_pc, 0);
-  DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.Size());
-  return branch_targets_.Get(dex_pc);
-}
-
-HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) {
-  HBasicBlock* block = FindBlockStartingAt(dex_pc);
-  if (block == nullptr) {
-    block = new (arena_) HBasicBlock(graph_, dex_pc);
-    branch_targets_.Put(dex_pc, block);
-  }
-  return block;
+HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
+  DCHECK_GE(index, 0);
+  return branch_targets_.Get(index);
 }
 
 template<typename T>
@@ -2259,29 +2108,15 @@
 
     case Instruction::MOVE_RESULT:
     case Instruction::MOVE_RESULT_WIDE:
-    case Instruction::MOVE_RESULT_OBJECT: {
+    case Instruction::MOVE_RESULT_OBJECT:
       if (latest_result_ == nullptr) {
         // Only dead code can lead to this situation, where the verifier
         // does not reject the method.
       } else {
-        // An Invoke/FilledNewArray and its MoveResult could have landed in
-        // different blocks if there was a try/catch block boundary between
-        // them. We need to insert the StoreLocal after the result definition
-        // but before any potential Temporaries.
-        HStoreLocal* update_local =
-            new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_);
-        HBasicBlock* block = latest_result_->GetBlock();
-        if (latest_result_->IsInvoke()) {
-          block->InsertInstructionAfter(update_local, latest_result_);
-        } else {
-          DCHECK(latest_result_->IsNewArray());
-          DCHECK(latest_result_->GetNext()->IsTemporary());
-          block->InsertInstructionAfter(update_local, latest_result_->GetNext());
-        }
+        UpdateLocal(instruction.VRegA(), latest_result_);
         latest_result_ = nullptr;
       }
       break;
-    }
 
     case Instruction::CMP_LONG: {
       Binop_23x_cmp(instruction, Primitive::kPrimLong, HCompare::kNoBias, dex_pc);