Build dominator tree before generating HInstructions

Second CL in the series of merging HGraphBuilder and SsaBuilder. This
patch refactors the builders so that dominator tree can be built
before any HInstructions are generated. This puts the SsaBuilder
removal of HLoadLocals/HStoreLocals straight after HGraphBuilder's
HInstruction generation phase. Next CL will therefore be able to
merge them.

This patch also adds util classes for iterating bytecode and switch
tables which allowed to simplify the code.

Bug: 27894376
Change-Id: Ic425d298b2e6e7980481ed697230b1a0b7904526
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 294d00f..5a05256 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -16,6 +16,7 @@
 
 #include "ssa_builder.h"
 
+#include "bytecode_utils.h"
 #include "nodes.h"
 #include "reference_type_propagation.h"
 #include "ssa_phi_elimination.h"
@@ -627,7 +628,6 @@
       // Make sure there was at least one throwing instruction which initialized
       // locals (guaranteed by HGraphBuilder) and that all try blocks have been
       // visited already (from HTryBoundary scoping and reverse post order).
-      bool throwing_instruction_found = false;
       bool catch_block_visited = false;
       for (HReversePostOrderIterator it(*GetGraph()); !it.Done(); it.Advance()) {
         HBasicBlock* current = it.Current();
@@ -636,10 +636,10 @@
         } else if (current->IsTryBlock() &&
                    current->GetTryCatchInformation()->GetTryEntry().HasExceptionHandler(*block)) {
           DCHECK(!catch_block_visited) << "Catch block visited before its try block.";
-          throwing_instruction_found |= current->HasThrowingInstructions();
         }
       }
-      DCHECK(throwing_instruction_found) << "No instructions throwing into a live catch block.";
+      DCHECK_EQ(current_locals_->size(), GetGraph()->GetNumberOfVRegs())
+          << "No instructions throwing into a live catch block.";
     }
   } else if (block->IsLoopHeader()) {
     // If the block is a loop header, we know we only have visited the pre header
@@ -899,6 +899,27 @@
   store->GetBlock()->RemoveInstruction(store);
 }
 
+bool SsaBuilder::IsFirstAtThrowingDexPc(HInstruction* instruction) const {
+  uint32_t dex_pc = instruction->GetDexPc();
+  if (dex_pc == kNoDexPc) {
+    return false;
+  }
+
+  // Needs to be the first HInstruction with this dex_pc.
+  HInstruction* previous = instruction->GetPrevious();
+  if (previous != nullptr && previous->GetDexPc() == dex_pc) {
+    return false;
+  }
+
+  if (instruction->IsControlFlow() && !instruction->IsThrow()) {
+    // Special-case non-throwing control-flow HInstruction because artifically
+    // created ones are given dex_pc of the nearest bytecode instructions.
+    return false;
+  }
+
+  return IsThrowingDexInstruction(GetDexInstructionAt(code_item_, dex_pc));
+}
+
 void SsaBuilder::VisitInstruction(HInstruction* instruction) {
   if (instruction->NeedsEnvironment()) {
     HEnvironment* environment = new (GetGraph()->GetArena()) HEnvironment(
@@ -914,7 +935,7 @@
   }
 
   // If in a try block, propagate values of locals into catch blocks.
-  if (instruction->CanThrowIntoCatchBlock()) {
+  if (instruction->GetBlock()->IsTryBlock() && IsFirstAtThrowingDexPc(instruction)) {
     const HTryBoundary& try_entry =
         instruction->GetBlock()->GetTryCatchInformation()->GetTryEntry();
     for (HBasicBlock* catch_block : try_entry.GetExceptionHandlers()) {