Optimizing: Tag basic block allocations with their source.

Replace GrowableArray with ArenaVector in HBasicBlock and,
to track the source of allocations, assign one new and two
Quick's arena allocation types to these vectors. Rename
kArenaAllocSuccessor to kArenaAllocSuccessors.

Bug: 23736311
Change-Id: Ib52e51698890675bde61f007fe6039338cf1a025
diff --git a/compiler/dex/global_value_numbering_test.cc b/compiler/dex/global_value_numbering_test.cc
index c8aa990..f2c2e22 100644
--- a/compiler/dex/global_value_numbering_test.cc
+++ b/compiler/dex/global_value_numbering_test.cc
@@ -202,7 +202,7 @@
         for (size_t j = 0u; j != def->num_successors; ++j) {
           SuccessorBlockInfo* successor_block_info =
               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
-                                                               kArenaAllocSuccessor));
+                                                               kArenaAllocSuccessors));
           successor_block_info->block = j;
           successor_block_info->key = 0u;  // Not used by class init check elimination.
           bb->successor_blocks.push_back(successor_block_info);
@@ -474,7 +474,7 @@
   BasicBlock* check_bb = cu_.mir_graph->GetBasicBlock(3u);
   check_bb->successor_block_list_type = kCatch;
   SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
-      (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+      (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessors));
   successor_block_info->block = catch_handler->id;
   check_bb->successor_blocks.push_back(successor_block_info);
 }
@@ -2284,7 +2284,7 @@
   BasicBlock* check_bb = cu_.mir_graph->GetBasicBlock(3u);
   check_bb->successor_block_list_type = kCatch;
   SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
-      (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+      (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessors));
   successor_block_info->block = catch_handler->id;
   check_bb->successor_blocks.push_back(successor_block_info);
   BasicBlock* merge_block = cu_.mir_graph->GetBasicBlock(4u);
diff --git a/compiler/dex/gvn_dead_code_elimination_test.cc b/compiler/dex/gvn_dead_code_elimination_test.cc
index 4df0a8b..28c61a8 100644
--- a/compiler/dex/gvn_dead_code_elimination_test.cc
+++ b/compiler/dex/gvn_dead_code_elimination_test.cc
@@ -209,7 +209,7 @@
         for (size_t j = 0u; j != def->num_successors; ++j) {
           SuccessorBlockInfo* successor_block_info =
               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
-                                                               kArenaAllocSuccessor));
+                                                               kArenaAllocSuccessors));
           successor_block_info->block = j;
           successor_block_info->key = 0u;  // Not used by class init check elimination.
           bb->successor_blocks.push_back(successor_block_info);
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 7976a9a..4efe4af 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -572,7 +572,7 @@
     DCHECK(case_block != nullptr);
     SuccessorBlockInfo* successor_block_info =
         static_cast<SuccessorBlockInfo*>(arena_->Alloc(sizeof(SuccessorBlockInfo),
-                                                       kArenaAllocSuccessor));
+                                                       kArenaAllocSuccessors));
     successor_block_info->block = case_block->id;
     successor_block_info->key =
         (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
@@ -627,7 +627,7 @@
         catches_.insert(catch_block->start_offset);
       }
       SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
-          (arena_->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+          (arena_->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessors));
       successor_block_info->block = catch_block->id;
       successor_block_info->key = iterator.GetHandlerTypeIndex();
       cur_block->successor_blocks.push_back(successor_block_info);
@@ -2178,7 +2178,7 @@
     result_bb->successor_blocks.reserve(successor_blocks.size());
     for (SuccessorBlockInfo* sbi_old : successor_blocks) {
       SuccessorBlockInfo* sbi_new = static_cast<SuccessorBlockInfo*>(
-          arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+          arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessors));
       memcpy(sbi_new, sbi_old, sizeof(SuccessorBlockInfo));
       result_bb->successor_blocks.push_back(sbi_new);
     }
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 1df6a4f..097abdc 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -379,7 +379,7 @@
         terminated_by_return(), dominates_return(), use_lvn(), first_mir_insn(),
         last_mir_insn(), data_flow_info(), dominators(), i_dominated(), dom_frontier(),
         predecessors(allocator->Adapter(kArenaAllocBBPredecessors)),
-        successor_blocks(allocator->Adapter(kArenaAllocSuccessor)) {
+        successor_blocks(allocator->Adapter(kArenaAllocSuccessors)) {
   }
   BasicBlockId id;
   BasicBlockId dfs_id;
diff --git a/compiler/dex/mir_graph_test.cc b/compiler/dex/mir_graph_test.cc
index 49b7511..7858681 100644
--- a/compiler/dex/mir_graph_test.cc
+++ b/compiler/dex/mir_graph_test.cc
@@ -79,7 +79,7 @@
         for (size_t j = 0u; j != def->num_successors; ++j) {
           SuccessorBlockInfo* successor_block_info =
               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
-                                                               kArenaAllocSuccessor));
+                                                               kArenaAllocSuccessors));
           successor_block_info->block = j;
           successor_block_info->key = 0u;  // Not used by class init check elimination.
           bb->successor_blocks.push_back(successor_block_info);
diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc
index 47123ba..a0cedff 100644
--- a/compiler/dex/mir_optimization_test.cc
+++ b/compiler/dex/mir_optimization_test.cc
@@ -118,7 +118,7 @@
         for (size_t j = 0u; j != def->num_successors; ++j) {
           SuccessorBlockInfo* successor_block_info =
               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
-                                                               kArenaAllocSuccessor));
+                                                               kArenaAllocSuccessors));
           successor_block_info->block = j;
           successor_block_info->key = 0u;  // Not used by class init check elimination.
           bb->successor_blocks.push_back(successor_block_info);
@@ -244,7 +244,7 @@
     BasicBlock* check_bb = cu_.mir_graph->GetBasicBlock(3u);
     check_bb->successor_block_list_type = kCatch;
     SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
-        (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
+        (cu_.arena.Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessors));
     successor_block_info->block = catch_handler->id;
     check_bb->successor_blocks.push_back(successor_block_info);
   }
diff --git a/compiler/dex/type_inference_test.cc b/compiler/dex/type_inference_test.cc
index 872a8d6..528a18c 100644
--- a/compiler/dex/type_inference_test.cc
+++ b/compiler/dex/type_inference_test.cc
@@ -322,7 +322,7 @@
         for (size_t j = 0u; j != def->num_successors; ++j) {
           SuccessorBlockInfo* successor_block_info =
               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
-                                                               kArenaAllocSuccessor));
+                                                               kArenaAllocSuccessors));
           successor_block_info->block = j;
           successor_block_info->key = 0u;  // Not used by class init check elimination.
           bb->successor_blocks.push_back(successor_block_info);
diff --git a/compiler/optimizing/boolean_simplifier.cc b/compiler/optimizing/boolean_simplifier.cc
index 84201c3..b0e83b0 100644
--- a/compiler/optimizing/boolean_simplifier.cc
+++ b/compiler/optimizing/boolean_simplifier.cc
@@ -42,9 +42,9 @@
 // successor and the successor can only be reached from them.
 static bool BlocksDoMergeTogether(HBasicBlock* block1, HBasicBlock* block2) {
   if (!block1->IsSingleGoto() || !block2->IsSingleGoto()) return false;
-  HBasicBlock* succ1 = block1->GetSuccessors().Get(0);
-  HBasicBlock* succ2 = block2->GetSuccessors().Get(0);
-  return succ1 == succ2 && succ1->GetPredecessors().Size() == 2u;
+  HBasicBlock* succ1 = block1->GetSuccessor(0);
+  HBasicBlock* succ2 = block2->GetSuccessor(0);
+  return succ1 == succ2 && succ1->GetPredecessors().size() == 2u;
 }
 
 // Returns true if the outcome of the branching matches the boolean value of
@@ -108,7 +108,7 @@
   if (!BlocksDoMergeTogether(true_block, false_block)) {
     return;
   }
-  HBasicBlock* merge_block = true_block->GetSuccessors().Get(0);
+  HBasicBlock* merge_block = true_block->GetSuccessor(0);
   if (!merge_block->HasSinglePhi()) {
     return;
   }
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index ebc0adc..70ad408 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -275,9 +275,8 @@
       // Loop header of loop_info. Exiting loop is normal.
       return false;
     }
-    const GrowableArray<HBasicBlock*>& successors = block->GetSuccessors();
-    for (size_t i = 0; i < successors.Size(); i++) {
-      if (!loop_info->Contains(*successors.Get(i))) {
+    for (HBasicBlock* successor : block->GetSuccessors()) {
+      if (!loop_info->Contains(*successor)) {
         // One of the successors exits the loop.
         return true;
       }
@@ -797,8 +796,8 @@
     HBasicBlock* new_pre_header = header->GetDominator();
     DCHECK(new_pre_header == header->GetLoopInformation()->GetPreHeader());
     HBasicBlock* if_block = new_pre_header->GetDominator();
-    HBasicBlock* dummy_block = if_block->GetSuccessors().Get(0);  // True successor.
-    HBasicBlock* deopt_block = if_block->GetSuccessors().Get(1);  // False successor.
+    HBasicBlock* dummy_block = if_block->GetSuccessor(0);  // True successor.
+    HBasicBlock* deopt_block = if_block->GetSuccessor(1);  // False successor.
 
     dummy_block->AddInstruction(new (graph->GetArena()) HGoto());
     deopt_block->AddInstruction(new (graph->GetArena()) HGoto());
@@ -845,14 +844,14 @@
     DCHECK(header->IsLoopHeader());
     HBasicBlock* pre_header = header->GetDominator();
     if (loop_entry_test_block_added) {
-      DCHECK(deopt_block->GetSuccessors().Get(0) == pre_header);
+      DCHECK(deopt_block->GetSuccessor(0) == pre_header);
     } else {
       DCHECK(deopt_block == pre_header);
     }
     HGraph* graph = header->GetGraph();
     HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
     if (loop_entry_test_block_added) {
-      DCHECK_EQ(deopt_block, header->GetDominator()->GetDominator()->GetSuccessors().Get(1));
+      DCHECK_EQ(deopt_block, header->GetDominator()->GetDominator()->GetSuccessor(1));
     }
 
     HIntConstant* const_instr = graph->GetIntConstant(constant);
@@ -926,7 +925,7 @@
     DCHECK(header->IsLoopHeader());
     HBasicBlock* pre_header = header->GetDominator();
     if (loop_entry_test_block_added) {
-      DCHECK(deopt_block->GetSuccessors().Get(0) == pre_header);
+      DCHECK(deopt_block->GetSuccessor(0) == pre_header);
     } else {
       DCHECK(deopt_block == pre_header);
     }
@@ -1256,11 +1255,11 @@
 
     HBasicBlock* true_successor = instruction->IfTrueSuccessor();
     // There should be no critical edge at this point.
-    DCHECK_EQ(true_successor->GetPredecessors().Size(), 1u);
+    DCHECK_EQ(true_successor->GetPredecessors().size(), 1u);
 
     HBasicBlock* false_successor = instruction->IfFalseSuccessor();
     // There should be no critical edge at this point.
-    DCHECK_EQ(false_successor->GetPredecessors().Size(), 1u);
+    DCHECK_EQ(false_successor->GetPredecessors().size(), 1u);
 
     ValueRange* left_range = LookupValueRange(left, block);
     MonotonicValueRange* left_monotonic_range = nullptr;
@@ -1468,10 +1467,10 @@
     // Start with input 1. Input 0 is from the incoming block.
     HInstruction* input1 = phi->InputAt(1);
     DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
-        *phi->GetBlock()->GetPredecessors().Get(1)));
+        *phi->GetBlock()->GetPredecessor(1)));
     for (size_t i = 2, e = phi->InputCount(); i < e; ++i) {
       DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
-          *phi->GetBlock()->GetPredecessors().Get(i)));
+          *phi->GetBlock()->GetPredecessor(i)));
       if (input1 != phi->InputAt(i)) {
         return false;
       }
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 1650fd1..7fa16bb 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -396,8 +396,8 @@
 
     // 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);
+    for (size_t i = 0; i < try_block->GetPredecessors().size(); ++i) {
+      HBasicBlock* predecessor = try_block->GetPredecessor(i);
       if (predecessor->IsSingleTryBoundary()) {
         // The edge was already split because of an exit from a neighbouring
         // TryItem. We split it again and insert an entry point.
@@ -424,8 +424,7 @@
 
     // 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);
+    for (HBasicBlock* successor : try_block->GetSuccessors()) {
       if (successor->IsCatchBlock()) {
         // A catch block is always considered an entry point into its TryItem.
         // We therefore assume this is an exit point, regardless of whether
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index a6fc455..f5c4498 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -171,7 +171,7 @@
 
 HBasicBlock* CodeGenerator::FirstNonEmptyBlock(HBasicBlock* block) const {
   while (block->IsSingleJump()) {
-    block = block->GetSuccessors().Get(0);
+    block = block->GetSuccessor(0);
   }
   return block;
 }
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 4fbb51d..72c67f5 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -561,7 +561,7 @@
   ASSERT_FALSE(equal->NeedsMaterialization());
 
   auto hook_before_codegen = [](HGraph* graph_in) {
-    HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
+    HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessor(0);
     HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
     block->InsertInstructionBefore(move, block->GetLastInstruction());
   };
@@ -667,7 +667,7 @@
     code_block->AddInstruction(&ret);
 
     auto hook_before_codegen = [](HGraph* graph_in) {
-      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
+      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessor(0);
       HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
       block->InsertInstructionBefore(move, block->GetLastInstruction());
     };
@@ -733,7 +733,7 @@
     if_false_block->AddInstruction(&ret_ge);
 
     auto hook_before_codegen = [](HGraph* graph_in) {
-      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors().Get(0);
+      HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessor(0);
       HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
       block->InsertInstructionBefore(move, block->GetLastInstruction());
     };
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 50cbf5c..509478c 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -42,8 +42,8 @@
       MarkReachableBlocks(if_instruction->IfFalseSuccessor(), visited);
     }
   } else {
-    for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
-      MarkReachableBlocks(block->GetSuccessors().Get(i), visited);
+    for (HBasicBlock* successor : block->GetSuccessors()) {
+      MarkReachableBlocks(successor, visited);
     }
   }
 }
@@ -99,12 +99,12 @@
   // Connect successive blocks created by dead branches. Order does not matter.
   for (HReversePostOrderIterator it(*graph_); !it.Done();) {
     HBasicBlock* block  = it.Current();
-    if (block->IsEntryBlock() || block->GetSuccessors().Size() != 1u) {
+    if (block->IsEntryBlock() || block->GetSuccessors().size() != 1u) {
       it.Advance();
       continue;
     }
-    HBasicBlock* successor = block->GetSuccessors().Get(0);
-    if (successor->IsExitBlock() || successor->GetPredecessors().Size() != 1u) {
+    HBasicBlock* successor = block->GetSuccessor(0);
+    if (successor->IsExitBlock() || successor->GetPredecessors().size() != 1u) {
       it.Advance();
       continue;
     }
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 847d5a4..3e35835 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -29,19 +29,16 @@
   current_block_ = block;
 
   // Check consistency with respect to predecessors of `block`.
-  const GrowableArray<HBasicBlock*>& predecessors = block->GetPredecessors();
   std::map<HBasicBlock*, size_t> predecessors_count;
-  for (size_t i = 0, e = predecessors.Size(); i < e; ++i) {
-    HBasicBlock* p = predecessors.Get(i);
+  for (HBasicBlock* p : block->GetPredecessors()) {
     ++predecessors_count[p];
   }
   for (auto& pc : predecessors_count) {
     HBasicBlock* p = pc.first;
     size_t p_count_in_block_predecessors = pc.second;
-    const GrowableArray<HBasicBlock*>& p_successors = p->GetSuccessors();
     size_t block_count_in_p_successors = 0;
-    for (size_t j = 0, f = p_successors.Size(); j < f; ++j) {
-      if (p_successors.Get(j) == block) {
+    for (HBasicBlock* p_successor : p->GetSuccessors()) {
+      if (p_successor == block) {
         ++block_count_in_p_successors;
       }
     }
@@ -55,19 +52,16 @@
   }
 
   // Check consistency with respect to successors of `block`.
-  const GrowableArray<HBasicBlock*>& successors = block->GetSuccessors();
   std::map<HBasicBlock*, size_t> successors_count;
-  for (size_t i = 0, e = successors.Size(); i < e; ++i) {
-    HBasicBlock* s = successors.Get(i);
+  for (HBasicBlock* s : block->GetSuccessors()) {
     ++successors_count[s];
   }
   for (auto& sc : successors_count) {
     HBasicBlock* s = sc.first;
     size_t s_count_in_block_successors = sc.second;
-    const GrowableArray<HBasicBlock*>& s_predecessors = s->GetPredecessors();
     size_t block_count_in_s_predecessors = 0;
-    for (size_t j = 0, f = s_predecessors.Size(); j < f; ++j) {
-      if (s_predecessors.Get(j) == block) {
+    for (HBasicBlock* s_predecessor : s->GetPredecessors()) {
+      if (s_predecessor == block) {
         ++block_count_in_s_predecessors;
       }
     }
@@ -92,8 +86,7 @@
   // Ensure that only Return(Void) and Throw jump to Exit. An exiting
   // TryBoundary may be between a Throw and the Exit if the Throw is in a try.
   if (block->IsExitBlock()) {
-    for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
-      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
       if (predecessor->IsSingleTryBoundary()
           && !predecessor->GetLastInstruction()->AsTryBoundary()->IsEntry()) {
         HBasicBlock* real_predecessor = predecessor->GetSinglePredecessor();
@@ -178,8 +171,7 @@
                             try_boundary->GetId(),
                             handler->GetBlockId()));
     }
-    if (current_block_->GetSuccessors().Contains(
-            handler, /* start_from */ it.CurrentSuccessorIndex() + 1)) {
+    if (current_block_->HasSuccessor(handler, it.CurrentSuccessorIndex() + 1)) {
       AddError(StringPrintf("Exception handler block %d of %s:%d is listed multiple times.",
                             handler->GetBlockId(),
                             try_boundary->DebugName(),
@@ -359,15 +351,15 @@
   // never exceptional successors.
   const size_t num_normal_successors = block->NumberOfNormalSuccessors();
   for (size_t j = 0; j < num_normal_successors; ++j) {
-    HBasicBlock* successor = block->GetSuccessors().Get(j);
+    HBasicBlock* successor = block->GetSuccessor(j);
     if (successor->IsCatchBlock()) {
       AddError(StringPrintf("Catch block %d is a normal successor of block %d.",
                             successor->GetBlockId(),
                             block->GetBlockId()));
     }
   }
-  for (size_t j = num_normal_successors, e = block->GetSuccessors().Size(); j < e; ++j) {
-    HBasicBlock* successor = block->GetSuccessors().Get(j);
+  for (size_t j = num_normal_successors, e = block->GetSuccessors().size(); j < e; ++j) {
+    HBasicBlock* successor = block->GetSuccessor(j);
     if (!successor->IsCatchBlock()) {
       AddError(StringPrintf("Normal block %d is an exceptional successor of block %d.",
                             successor->GetBlockId(),
@@ -381,8 +373,8 @@
   // not accounted for.
   if (block->NumberOfNormalSuccessors() > 1) {
     for (size_t j = 0, e = block->NumberOfNormalSuccessors(); j < e; ++j) {
-      HBasicBlock* successor = block->GetSuccessors().Get(j);
-      if (successor->GetPredecessors().Size() > 1) {
+      HBasicBlock* successor = block->GetSuccessor(j);
+      if (successor->GetPredecessors().size() > 1) {
         AddError(StringPrintf("Critical edge between blocks %d and %d.",
                               block->GetBlockId(),
                               successor->GetBlockId()));
@@ -417,8 +409,7 @@
                             block->GetBlockId()));
     }
   } else {
-    for (size_t i = 0; i < block->GetPredecessors().Size(); ++i) {
-      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
       const HTryBoundary* incoming_try_entry = predecessor->ComputeTryEntryOfSuccessors();
       if (block->IsTryBlock()) {
         const HTryBoundary& stored_try_entry = block->GetTryCatchInformation()->GetTryEntry();
@@ -469,21 +460,21 @@
 
   // Ensure the loop header has only one incoming branch and the remaining
   // predecessors are back edges.
-  size_t num_preds = loop_header->GetPredecessors().Size();
+  size_t num_preds = loop_header->GetPredecessors().size();
   if (num_preds < 2) {
     AddError(StringPrintf(
         "Loop header %d has less than two predecessors: %zu.",
         id,
         num_preds));
   } else {
-    HBasicBlock* first_predecessor = loop_header->GetPredecessors().Get(0);
+    HBasicBlock* first_predecessor = loop_header->GetPredecessor(0);
     if (loop_information->IsBackEdge(*first_predecessor)) {
       AddError(StringPrintf(
           "First predecessor of loop header %d is a back edge.",
           id));
     }
-    for (size_t i = 1, e = loop_header->GetPredecessors().Size(); i < e; ++i) {
-      HBasicBlock* predecessor = loop_header->GetPredecessors().Get(i);
+    for (size_t i = 1, e = loop_header->GetPredecessors().size(); i < e; ++i) {
+      HBasicBlock* predecessor = loop_header->GetPredecessor(i);
       if (!loop_information->IsBackEdge(*predecessor)) {
         AddError(StringPrintf(
             "Loop header %d has multiple incoming (non back edge) blocks.",
@@ -621,20 +612,19 @@
   } else {
     // Ensure the number of inputs of a non-catch phi is the same as the number
     // of its predecessors.
-    const GrowableArray<HBasicBlock*>& predecessors =
-        phi->GetBlock()->GetPredecessors();
-    if (phi->InputCount() != predecessors.Size()) {
+    const ArenaVector<HBasicBlock*>& predecessors = phi->GetBlock()->GetPredecessors();
+    if (phi->InputCount() != predecessors.size()) {
       AddError(StringPrintf(
           "Phi %d in block %d has %zu inputs, "
           "but block %d has %zu predecessors.",
           phi->GetId(), phi->GetBlock()->GetBlockId(), phi->InputCount(),
-          phi->GetBlock()->GetBlockId(), predecessors.Size()));
+          phi->GetBlock()->GetBlockId(), predecessors.size()));
     } else {
       // Ensure phi input at index I either comes from the Ith
       // predecessor or from a block that dominates this predecessor.
       for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
         HInstruction* input = phi->InputAt(i);
-        HBasicBlock* predecessor = predecessors.Get(i);
+        HBasicBlock* predecessor = predecessors[i];
         if (!(input->GetBlock() == predecessor
               || input->GetBlock()->Dominates(predecessor))) {
           AddError(StringPrintf(
diff --git a/compiler/optimizing/graph_test.cc b/compiler/optimizing/graph_test.cc
index 59d5092..7968e88 100644
--- a/compiler/optimizing/graph_test.cc
+++ b/compiler/optimizing/graph_test.cc
@@ -99,7 +99,7 @@
   ASSERT_NE(false_block, return_block);
 
   // Ensure the new block branches to the join block.
-  ASSERT_EQ(false_block->GetSuccessors().Get(0), return_block);
+  ASSERT_EQ(false_block->GetSuccessor(0), return_block);
 }
 
 // Test that the successors of an if block stay consistent after a SimplifyCFG.
@@ -134,7 +134,7 @@
   ASSERT_NE(true_block, return_block);
 
   // Ensure the new block branches to the join block.
-  ASSERT_EQ(true_block->GetSuccessors().Get(0), return_block);
+  ASSERT_EQ(true_block->GetSuccessor(0), return_block);
 }
 
 // Test that the successors of an if block stay consistent after a SimplifyCFG.
@@ -163,12 +163,12 @@
   ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), return_block);
 
   // Ensure there is only one back edge.
-  ASSERT_EQ(if_block->GetPredecessors().Size(), 2u);
-  ASSERT_EQ(if_block->GetPredecessors().Get(0), entry_block);
-  ASSERT_NE(if_block->GetPredecessors().Get(1), if_block);
+  ASSERT_EQ(if_block->GetPredecessors().size(), 2u);
+  ASSERT_EQ(if_block->GetPredecessor(0), entry_block);
+  ASSERT_NE(if_block->GetPredecessor(1), if_block);
 
   // Ensure the new block is the back edge.
-  ASSERT_EQ(if_block->GetPredecessors().Get(1),
+  ASSERT_EQ(if_block->GetPredecessor(1),
             if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor());
 }
 
@@ -198,12 +198,12 @@
   ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), return_block);
 
   // Ensure there is only one back edge.
-  ASSERT_EQ(if_block->GetPredecessors().Size(), 2u);
-  ASSERT_EQ(if_block->GetPredecessors().Get(0), entry_block);
-  ASSERT_NE(if_block->GetPredecessors().Get(1), if_block);
+  ASSERT_EQ(if_block->GetPredecessors().size(), 2u);
+  ASSERT_EQ(if_block->GetPredecessor(0), entry_block);
+  ASSERT_NE(if_block->GetPredecessor(1), if_block);
 
   // Ensure the new block is the back edge.
-  ASSERT_EQ(if_block->GetPredecessors().Get(1),
+  ASSERT_EQ(if_block->GetPredecessor(1),
             if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor());
 }
 
@@ -238,11 +238,11 @@
   ASSERT_EQ(if_instr->IfFalseSuccessor(), return_block);
 
   // Ensure there is only one pre header..
-  ASSERT_EQ(loop_block->GetPredecessors().Size(), 2u);
+  ASSERT_EQ(loop_block->GetPredecessors().size(), 2u);
 
   // Ensure the new block is the successor of the true block.
-  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessors().Size(), 1u);
-  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessors().Get(0),
+  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessors().size(), 1u);
+  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessor(0),
             loop_block->GetLoopInformation()->GetPreHeader());
 }
 
@@ -276,11 +276,11 @@
   ASSERT_EQ(if_instr->IfTrueSuccessor(), return_block);
 
   // Ensure there is only one pre header..
-  ASSERT_EQ(loop_block->GetPredecessors().Size(), 2u);
+  ASSERT_EQ(loop_block->GetPredecessors().size(), 2u);
 
   // Ensure the new block is the successor of the false block.
-  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessors().Size(), 1u);
-  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessors().Get(0),
+  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessors().size(), 1u);
+  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessor(0),
             loop_block->GetLoopInformation()->GetPreHeader());
 }
 
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 069a7a4..5b8e386 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -240,8 +240,7 @@
   void PrintPredecessors(HBasicBlock* block) {
     AddIndent();
     output_ << "predecessors";
-    for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
-      HBasicBlock* predecessor = block->GetPredecessors().Get(i);
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
       output_ << " \"B" << predecessor->GetBlockId() << "\" ";
     }
     if (block->IsEntryBlock() && (disasm_info_ != nullptr)) {
@@ -254,7 +253,7 @@
     AddIndent();
     output_ << "successors";
     for (size_t i = 0; i < block->NumberOfNormalSuccessors(); ++i) {
-      HBasicBlock* successor = block->GetSuccessors().Get(i);
+      HBasicBlock* successor = block->GetSuccessor(i);
       output_ << " \"B" << successor->GetBlockId() << "\" ";
     }
     output_<< std::endl;
@@ -263,8 +262,8 @@
   void PrintExceptionHandlers(HBasicBlock* block) {
     AddIndent();
     output_ << "xhandlers";
-    for (size_t i = block->NumberOfNormalSuccessors(); i < block->GetSuccessors().Size(); ++i) {
-      HBasicBlock* handler = block->GetSuccessors().Get(i);
+    for (size_t i = block->NumberOfNormalSuccessors(); i < block->GetSuccessors().size(); ++i) {
+      HBasicBlock* handler = block->GetSuccessor(i);
       output_ << " \"B" << handler->GetBlockId() << "\" ";
     }
     if (block->IsExitBlock() &&
diff --git a/compiler/optimizing/gvn.cc b/compiler/optimizing/gvn.cc
index 833dfb0..5bb4e8e 100644
--- a/compiler/optimizing/gvn.cc
+++ b/compiler/optimizing/gvn.cc
@@ -340,8 +340,8 @@
 
 void GlobalValueNumberer::VisitBasicBlock(HBasicBlock* block) {
   ValueSet* set = nullptr;
-  const GrowableArray<HBasicBlock*>& predecessors = block->GetPredecessors();
-  if (predecessors.Size() == 0 || predecessors.Get(0)->IsEntryBlock()) {
+  const ArenaVector<HBasicBlock*>& predecessors = block->GetPredecessors();
+  if (predecessors.size() == 0 || predecessors[0]->IsEntryBlock()) {
     // The entry block should only accumulate constant instructions, and
     // the builder puts constants only in the entry block.
     // Therefore, there is no need to propagate the value set to the next block.
@@ -349,8 +349,8 @@
   } else {
     HBasicBlock* dominator = block->GetDominator();
     ValueSet* dominator_set = sets_.Get(dominator->GetBlockId());
-    if (dominator->GetSuccessors().Size() == 1) {
-      DCHECK_EQ(dominator->GetSuccessors().Get(0), block);
+    if (dominator->GetSuccessors().size() == 1) {
+      DCHECK_EQ(dominator->GetSuccessor(0), block);
       set = dominator_set;
     } else {
       // We have to copy if the dominator has other successors, or `block` is not a successor
@@ -361,9 +361,9 @@
       if (block->IsLoopHeader()) {
         DCHECK_EQ(block->GetDominator(), block->GetLoopInformation()->GetPreHeader());
         set->Kill(side_effects_.GetLoopEffects(block));
-      } else if (predecessors.Size() > 1) {
-        for (size_t i = 0, e = predecessors.Size(); i < e; ++i) {
-          set->IntersectWith(sets_.Get(predecessors.Get(i)->GetBlockId()));
+      } else if (predecessors.size() > 1) {
+        for (HBasicBlock* predecessor : predecessors) {
+          set->IntersectWith(sets_.Get(predecessor->GetBlockId()));
           if (set->IsEmpty()) {
             break;
           }
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index b5870ae..bd591f3 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -423,8 +423,8 @@
   }
 
   bool has_throw_predecessor = false;
-  for (size_t i = 0, e = exit_block->GetPredecessors().Size(); i < e; ++i) {
-    if (exit_block->GetPredecessors().Get(i)->GetLastInstruction()->IsThrow()) {
+  for (HBasicBlock* predecessor : exit_block->GetPredecessors()) {
+    if (predecessor->GetLastInstruction()->IsThrow()) {
       has_throw_predecessor = true;
       break;
     }
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 4332d7e..62a460a 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -68,8 +68,8 @@
     if (!visited.IsBitSet(i)) {
       HBasicBlock* block = blocks_.Get(i);
       // We only need to update the successor, which might be live.
-      for (size_t j = 0; j < block->GetSuccessors().Size(); ++j) {
-        block->GetSuccessors().Get(j)->RemovePredecessor(block);
+      for (HBasicBlock* successor : block->GetSuccessors()) {
+        successor->RemovePredecessor(block);
       }
       // Remove the block from the list of blocks, so that further analyses
       // never see it.
@@ -86,8 +86,7 @@
 
   visited->SetBit(id);
   visiting->SetBit(id);
-  for (size_t i = 0; i < block->GetSuccessors().Size(); i++) {
-    HBasicBlock* successor = block->GetSuccessors().Get(i);
+  for (HBasicBlock* successor : block->GetSuccessors()) {
     if (visiting->IsBitSet(successor->GetBlockId())) {
       successor->AddBackEdge(block);
     } else {
@@ -134,7 +133,7 @@
 }
 
 void HBasicBlock::ClearDominanceInformation() {
-  dominated_blocks_.Reset();
+  dominated_blocks_.clear();
   dominator_ = nullptr;
 }
 
@@ -143,8 +142,8 @@
   GrowableArray<size_t> visits(arena_, blocks_.Size());
   visits.SetSize(blocks_.Size());
   reverse_post_order_.Add(entry_block_);
-  for (size_t i = 0; i < entry_block_->GetSuccessors().Size(); i++) {
-    VisitBlockForDominatorTree(entry_block_->GetSuccessors().Get(i), entry_block_, &visits);
+  for (HBasicBlock* successor : entry_block_->GetSuccessors()) {
+    VisitBlockForDominatorTree(successor, entry_block_, &visits);
   }
 }
 
@@ -179,11 +178,11 @@
   // Once all the forward edges have been visited, we know the immediate
   // dominator of the block. We can then start visiting its successors.
   if (visits->Get(block->GetBlockId()) ==
-      block->GetPredecessors().Size() - block->NumberOfBackEdges()) {
+      block->GetPredecessors().size() - block->NumberOfBackEdges()) {
     block->GetDominator()->AddDominatedBlock(block);
     reverse_post_order_.Add(block);
-    for (size_t i = 0; i < block->GetSuccessors().Size(); i++) {
-      VisitBlockForDominatorTree(block->GetSuccessors().Get(i), block, visits);
+    for (HBasicBlock* successor : block->GetSuccessors()) {
+      VisitBlockForDominatorTree(successor, block, visits);
     }
   }
 }
@@ -224,14 +223,14 @@
   // Make sure the loop has only one pre header. This simplifies SSA building by having
   // to just look at the pre header to know which locals are initialized at entry of the
   // loop.
-  size_t number_of_incomings = header->GetPredecessors().Size() - info->NumberOfBackEdges();
+  size_t number_of_incomings = header->GetPredecessors().size() - info->NumberOfBackEdges();
   if (number_of_incomings != 1) {
     HBasicBlock* pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
     AddBlock(pre_header);
     pre_header->AddInstruction(new (arena_) HGoto());
 
-    for (size_t pred = 0; pred < header->GetPredecessors().Size(); ++pred) {
-      HBasicBlock* predecessor = header->GetPredecessors().Get(pred);
+    for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) {
+      HBasicBlock* predecessor = header->GetPredecessor(pred);
       if (!info->IsBackEdge(*predecessor)) {
         predecessor->ReplaceSuccessor(header, pre_header);
         pred--;
@@ -241,13 +240,13 @@
   }
 
   // Make sure the first predecessor of a loop header is the incoming block.
-  if (info->IsBackEdge(*header->GetPredecessors().Get(0))) {
-    HBasicBlock* to_swap = header->GetPredecessors().Get(0);
-    for (size_t pred = 1, e = header->GetPredecessors().Size(); pred < e; ++pred) {
-      HBasicBlock* predecessor = header->GetPredecessors().Get(pred);
+  if (info->IsBackEdge(*header->GetPredecessor(0))) {
+    HBasicBlock* to_swap = header->GetPredecessor(0);
+    for (size_t pred = 1, e = header->GetPredecessors().size(); pred < e; ++pred) {
+      HBasicBlock* predecessor = header->GetPredecessor(pred);
       if (!info->IsBackEdge(*predecessor)) {
-        header->predecessors_.Put(pred, to_swap);
-        header->predecessors_.Put(0, predecessor);
+        header->predecessors_[pred] = to_swap;
+        header->predecessors_[0] = predecessor;
         break;
       }
     }
@@ -267,7 +266,7 @@
 }
 
 static bool CheckIfPredecessorAtIsExceptional(const HBasicBlock& block, size_t pred_idx) {
-  HBasicBlock* predecessor = block.GetPredecessors().Get(pred_idx);
+  HBasicBlock* predecessor = block.GetPredecessor(pred_idx);
   if (!predecessor->EndsWithTryBoundary()) {
     // Only edges from HTryBoundary can be exceptional.
     return false;
@@ -296,7 +295,7 @@
     }
 
     bool exceptional_predecessors_only = true;
-    for (size_t j = 0; j < catch_block->GetPredecessors().Size(); ++j) {
+    for (size_t j = 0; j < catch_block->GetPredecessors().size(); ++j) {
       if (!CheckIfPredecessorAtIsExceptional(*catch_block, j)) {
         exceptional_predecessors_only = false;
         break;
@@ -313,9 +312,9 @@
       // a MOVE_EXCEPTION instruction, as guaranteed by the verifier.
       DCHECK(!catch_block->GetFirstInstruction()->IsLoadException());
       HBasicBlock* normal_block = catch_block->SplitBefore(catch_block->GetFirstInstruction());
-      for (size_t j = 0; j < catch_block->GetPredecessors().Size(); ++j) {
+      for (size_t j = 0; j < catch_block->GetPredecessors().size(); ++j) {
         if (!CheckIfPredecessorAtIsExceptional(*catch_block, j)) {
-          catch_block->GetPredecessors().Get(j)->ReplaceSuccessor(catch_block, normal_block);
+          catch_block->GetPredecessor(j)->ReplaceSuccessor(catch_block, normal_block);
           --j;
         }
       }
@@ -337,7 +336,7 @@
     // Infer try membership from the first predecessor. Having simplified loops,
     // the first predecessor can never be a back edge and therefore it must have
     // been visited already and had its try membership set.
-    HBasicBlock* first_predecessor = block->GetPredecessors().Get(0);
+    HBasicBlock* first_predecessor = block->GetPredecessor(0);
     DCHECK(!block->IsLoopHeader() || !block->GetLoopInformation()->IsBackEdge(*first_predecessor));
     const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors();
     if (try_entry != nullptr) {
@@ -364,10 +363,10 @@
     HBasicBlock* block = blocks_.Get(i);
     if (block == nullptr) continue;
     if (block->NumberOfNormalSuccessors() > 1) {
-      for (size_t j = 0; j < block->GetSuccessors().Size(); ++j) {
-        HBasicBlock* successor = block->GetSuccessors().Get(j);
+      for (size_t j = 0; j < block->GetSuccessors().size(); ++j) {
+        HBasicBlock* successor = block->GetSuccessor(j);
         DCHECK(!successor->IsCatchBlock());
-        if (successor->GetPredecessors().Size() > 1) {
+        if (successor->GetPredecessors().size() > 1) {
           SplitCriticalEdge(block, successor);
           --j;
         }
@@ -485,8 +484,8 @@
 
   blocks_.SetBit(block->GetBlockId());
   block->SetInLoop(this);
-  for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
-    PopulateRecursive(block->GetPredecessors().Get(i));
+  for (HBasicBlock* predecessor : block->GetPredecessors()) {
+    PopulateRecursive(predecessor);
   }
 }
 
@@ -1136,12 +1135,11 @@
   new_block->instructions_.SetBlockOfInstructions(new_block);
   AddInstruction(new (GetGraph()->GetArena()) HGoto());
 
-  for (size_t i = 0, e = GetSuccessors().Size(); i < e; ++i) {
-    HBasicBlock* successor = GetSuccessors().Get(i);
-    new_block->successors_.Add(successor);
-    successor->predecessors_.Put(successor->GetPredecessorIndexOf(this), new_block);
+  for (HBasicBlock* successor : GetSuccessors()) {
+    new_block->successors_.push_back(successor);
+    successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
   }
-  successors_.Reset();
+  successors_.clear();
   AddSuccessor(new_block);
 
   GetGraph()->AddBlock(new_block);
@@ -1161,19 +1159,17 @@
   instructions_.last_instruction_ = cursor;
 
   new_block->instructions_.SetBlockOfInstructions(new_block);
-  for (size_t i = 0, e = GetSuccessors().Size(); i < e; ++i) {
-    HBasicBlock* successor = GetSuccessors().Get(i);
-    new_block->successors_.Add(successor);
-    successor->predecessors_.Put(successor->GetPredecessorIndexOf(this), new_block);
+  for (HBasicBlock* successor : GetSuccessors()) {
+    new_block->successors_.push_back(successor);
+    successor->predecessors_[successor->GetPredecessorIndexOf(this)] = new_block;
   }
-  successors_.Reset();
+  successors_.clear();
 
-  for (size_t i = 0, e = GetDominatedBlocks().Size(); i < e; ++i) {
-    HBasicBlock* dominated = GetDominatedBlocks().Get(i);
+  for (HBasicBlock* dominated : GetDominatedBlocks()) {
     dominated->dominator_ = new_block;
-    new_block->dominated_blocks_.Add(dominated);
+    new_block->dominated_blocks_.push_back(dominated);
   }
-  dominated_blocks_.Reset();
+  dominated_blocks_.clear();
   return new_block;
 }
 
@@ -1226,7 +1222,7 @@
 }
 
 bool HTryBoundary::HasSameExceptionHandlersAs(const HTryBoundary& other) const {
-  if (GetBlock()->GetSuccessors().Size() != other.GetBlock()->GetSuccessors().Size()) {
+  if (GetBlock()->GetSuccessors().size() != other.GetBlock()->GetSuccessors().size()) {
     return false;
   }
 
@@ -1286,7 +1282,7 @@
   // Dominators must be removed after all the blocks they dominate. This way
   // a loop header is removed last, a requirement for correct loop information
   // iteration.
-  DCHECK(dominated_blocks_.IsEmpty());
+  DCHECK(dominated_blocks_.empty());
 
   // Remove the block from all loops it is included in.
   for (HLoopInformationOutwardIterator it(*this); !it.Done(); it.Advance()) {
@@ -1302,36 +1298,34 @@
 
   // Disconnect the block from its predecessors and update their control-flow
   // instructions.
-  for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
-    HBasicBlock* predecessor = predecessors_.Get(i);
+  for (HBasicBlock* predecessor : predecessors_) {
     HInstruction* last_instruction = predecessor->GetLastInstruction();
     predecessor->RemoveInstruction(last_instruction);
     predecessor->RemoveSuccessor(this);
-    if (predecessor->GetSuccessors().Size() == 1u) {
+    if (predecessor->GetSuccessors().size() == 1u) {
       DCHECK(last_instruction->IsIf());
       predecessor->AddInstruction(new (graph_->GetArena()) HGoto());
     } else {
       // The predecessor has no remaining successors and therefore must be dead.
       // We deliberately leave it without a control-flow instruction so that the
       // SSAChecker fails unless it is not removed during the pass too.
-      DCHECK_EQ(predecessor->GetSuccessors().Size(), 0u);
+      DCHECK_EQ(predecessor->GetSuccessors().size(), 0u);
     }
   }
-  predecessors_.Reset();
+  predecessors_.clear();
 
   // Disconnect the block from its successors and update their phis.
-  for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
-    HBasicBlock* successor = successors_.Get(i);
+  for (HBasicBlock* successor : successors_) {
     // Delete this block from the list of predecessors.
     size_t this_index = successor->GetPredecessorIndexOf(this);
-    successor->predecessors_.DeleteAt(this_index);
+    successor->predecessors_.erase(successor->predecessors_.begin() + this_index);
 
     // Check that `successor` has other predecessors, otherwise `this` is the
     // dominator of `successor` which violates the order DCHECKed at the top.
-    DCHECK(!successor->predecessors_.IsEmpty());
+    DCHECK(!successor->predecessors_.empty());
 
     // Remove this block's entries in the successor's phis.
-    if (successor->predecessors_.Size() == 1u) {
+    if (successor->predecessors_.size() == 1u) {
       // The successor has just one predecessor left. Replace phis with the only
       // remaining input.
       for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
@@ -1345,7 +1339,7 @@
       }
     }
   }
-  successors_.Reset();
+  successors_.clear();
 
   // Disconnect from the dominator.
   dominator_->RemoveDominatedBlock(this);
@@ -1359,11 +1353,9 @@
 
 void HBasicBlock::MergeWith(HBasicBlock* other) {
   DCHECK_EQ(GetGraph(), other->GetGraph());
-  DCHECK(GetDominatedBlocks().Contains(other));
-  DCHECK_EQ(GetSuccessors().Size(), 1u);
-  DCHECK_EQ(GetSuccessors().Get(0), other);
-  DCHECK_EQ(other->GetPredecessors().Size(), 1u);
-  DCHECK_EQ(other->GetPredecessors().Get(0), this);
+  DCHECK(ContainsElement(dominated_blocks_, other));
+  DCHECK_EQ(GetSingleSuccessor(), other);
+  DCHECK_EQ(other->GetSinglePredecessor(), this);
   DCHECK(other->GetPhis().IsEmpty());
 
   // Move instructions from `other` to `this`.
@@ -1383,24 +1375,23 @@
   }
 
   // Update links to the successors of `other`.
-  successors_.Reset();
-  while (!other->successors_.IsEmpty()) {
-    HBasicBlock* successor = other->successors_.Get(0);
+  successors_.clear();
+  while (!other->successors_.empty()) {
+    HBasicBlock* successor = other->GetSuccessor(0);
     successor->ReplacePredecessor(other, this);
   }
 
   // Update the dominator tree.
-  dominated_blocks_.Delete(other);
-  for (size_t i = 0, e = other->GetDominatedBlocks().Size(); i < e; ++i) {
-    HBasicBlock* dominated = other->GetDominatedBlocks().Get(i);
-    dominated_blocks_.Add(dominated);
+  RemoveDominatedBlock(other);
+  for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
+    dominated_blocks_.push_back(dominated);
     dominated->SetDominator(this);
   }
-  other->dominated_blocks_.Reset();
+  other->dominated_blocks_.clear();
   other->dominator_ = nullptr;
 
   // Clear the list of predecessors of `other` in preparation of deleting it.
-  other->predecessors_.Reset();
+  other->predecessors_.clear();
 
   // Delete `other` from the graph. The function updates reverse post order.
   graph_->DeleteDeadBlock(other);
@@ -1409,11 +1400,10 @@
 
 void HBasicBlock::MergeWithInlined(HBasicBlock* other) {
   DCHECK_NE(GetGraph(), other->GetGraph());
-  DCHECK(GetDominatedBlocks().IsEmpty());
-  DCHECK(GetSuccessors().IsEmpty());
+  DCHECK(GetDominatedBlocks().empty());
+  DCHECK(GetSuccessors().empty());
   DCHECK(!EndsWithControlFlowInstruction());
-  DCHECK_EQ(other->GetPredecessors().Size(), 1u);
-  DCHECK(other->GetPredecessors().Get(0)->IsEntryBlock());
+  DCHECK(other->GetSinglePredecessor()->IsEntryBlock());
   DCHECK(other->GetPhis().IsEmpty());
   DCHECK(!other->IsInLoop());
 
@@ -1422,34 +1412,33 @@
   other->instructions_.SetBlockOfInstructions(this);
 
   // Update links to the successors of `other`.
-  successors_.Reset();
-  while (!other->successors_.IsEmpty()) {
-    HBasicBlock* successor = other->successors_.Get(0);
+  successors_.clear();
+  while (!other->successors_.empty()) {
+    HBasicBlock* successor = other->GetSuccessor(0);
     successor->ReplacePredecessor(other, this);
   }
 
   // Update the dominator tree.
-  for (size_t i = 0, e = other->GetDominatedBlocks().Size(); i < e; ++i) {
-    HBasicBlock* dominated = other->GetDominatedBlocks().Get(i);
-    dominated_blocks_.Add(dominated);
+  for (HBasicBlock* dominated : other->GetDominatedBlocks()) {
+    dominated_blocks_.push_back(dominated);
     dominated->SetDominator(this);
   }
-  other->dominated_blocks_.Reset();
+  other->dominated_blocks_.clear();
   other->dominator_ = nullptr;
   other->graph_ = nullptr;
 }
 
 void HBasicBlock::ReplaceWith(HBasicBlock* other) {
-  while (!GetPredecessors().IsEmpty()) {
-    HBasicBlock* predecessor = GetPredecessors().Get(0);
+  while (!GetPredecessors().empty()) {
+    HBasicBlock* predecessor = GetPredecessor(0);
     predecessor->ReplaceSuccessor(this, other);
   }
-  while (!GetSuccessors().IsEmpty()) {
-    HBasicBlock* successor = GetSuccessors().Get(0);
+  while (!GetSuccessors().empty()) {
+    HBasicBlock* successor = GetSuccessor(0);
     successor->ReplacePredecessor(this, other);
   }
-  for (size_t i = 0; i < dominated_blocks_.Size(); ++i) {
-    other->AddDominatedBlock(dominated_blocks_.Get(i));
+  for (HBasicBlock* dominated : GetDominatedBlocks()) {
+    other->AddDominatedBlock(dominated);
   }
   GetDominator()->ReplaceDominatedBlock(this, other);
   other->SetDominator(GetDominator());
@@ -1472,9 +1461,9 @@
 
 void HGraph::DeleteDeadBlock(HBasicBlock* block) {
   DCHECK_EQ(block->GetGraph(), this);
-  DCHECK(block->GetSuccessors().IsEmpty());
-  DCHECK(block->GetPredecessors().IsEmpty());
-  DCHECK(block->GetDominatedBlocks().IsEmpty());
+  DCHECK(block->GetSuccessors().empty());
+  DCHECK(block->GetPredecessors().empty());
+  DCHECK(block->GetDominatedBlocks().empty());
   DCHECK(block->GetDominator() == nullptr);
 
   for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
@@ -1548,16 +1537,16 @@
     HBasicBlock* at = invoke->GetBlock();
     HBasicBlock* to = at->SplitAfter(invoke);
 
-    HBasicBlock* first = entry_block_->GetSuccessors().Get(0);
+    HBasicBlock* first = entry_block_->GetSuccessor(0);
     DCHECK(!first->IsInLoop());
     at->MergeWithInlined(first);
     exit_block_->ReplaceWith(to);
 
     // Update all predecessors of the exit block (now the `to` block)
     // to not `HReturn` but `HGoto` instead.
-    bool returns_void = to->GetPredecessors().Get(0)->GetLastInstruction()->IsReturnVoid();
-    if (to->GetPredecessors().Size() == 1) {
-      HBasicBlock* predecessor = to->GetPredecessors().Get(0);
+    bool returns_void = to->GetPredecessor(0)->GetLastInstruction()->IsReturnVoid();
+    if (to->GetPredecessors().size() == 1) {
+      HBasicBlock* predecessor = to->GetPredecessor(0);
       HInstruction* last = predecessor->GetLastInstruction();
       if (!returns_void) {
         return_value = last->InputAt(0);
@@ -1571,8 +1560,7 @@
             allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()));
         to->AddPhi(return_value->AsPhi());
       }
-      for (size_t i = 0, e = to->GetPredecessors().Size(); i < e; ++i) {
-        HBasicBlock* predecessor = to->GetPredecessors().Get(i);
+      for (HBasicBlock* predecessor : to->GetPredecessors()) {
         HInstruction* last = predecessor->GetLastInstruction();
         if (!returns_void) {
           return_value->AsPhi()->AddInput(last->InputAt(0));
@@ -1720,8 +1708,8 @@
   AddBlock(new_pre_header);
 
   header->ReplacePredecessor(pre_header, new_pre_header);
-  pre_header->successors_.Reset();
-  pre_header->dominated_blocks_.Reset();
+  pre_header->successors_.clear();
+  pre_header->dominated_blocks_.clear();
 
   pre_header->AddSuccessor(if_block);
   if_block->AddSuccessor(dummy_block);  // True successor
@@ -1729,15 +1717,15 @@
   dummy_block->AddSuccessor(new_pre_header);
   deopt_block->AddSuccessor(new_pre_header);
 
-  pre_header->dominated_blocks_.Add(if_block);
+  pre_header->dominated_blocks_.push_back(if_block);
   if_block->SetDominator(pre_header);
-  if_block->dominated_blocks_.Add(dummy_block);
+  if_block->dominated_blocks_.push_back(dummy_block);
   dummy_block->SetDominator(if_block);
-  if_block->dominated_blocks_.Add(deopt_block);
+  if_block->dominated_blocks_.push_back(deopt_block);
   deopt_block->SetDominator(if_block);
-  if_block->dominated_blocks_.Add(new_pre_header);
+  if_block->dominated_blocks_.push_back(new_pre_header);
   new_pre_header->SetDominator(if_block);
-  new_pre_header->dominated_blocks_.Add(header);
+  new_pre_header->dominated_blocks_.push_back(header);
   header->SetDominator(new_pre_header);
 
   size_t index_of_header = 0;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index fef6f21..06a65e3 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -17,11 +17,13 @@
 #ifndef ART_COMPILER_OPTIMIZING_NODES_H_
 #define ART_COMPILER_OPTIMIZING_NODES_H_
 
+#include <algorithm>
 #include <array>
 #include <type_traits>
 
 #include "base/arena_containers.h"
 #include "base/arena_object.h"
+#include "base/stl_util.h"
 #include "dex/compiler_enums.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
 #include "handle.h"
@@ -628,26 +630,44 @@
  public:
   explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
       : graph_(graph),
-        predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
-        successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
+        predecessors_(graph->GetArena()->Adapter(kArenaAllocPredecessors)),
+        successors_(graph->GetArena()->Adapter(kArenaAllocSuccessors)),
         loop_information_(nullptr),
         dominator_(nullptr),
-        dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
+        dominated_blocks_(graph->GetArena()->Adapter(kArenaAllocDominated)),
         block_id_(-1),
         dex_pc_(dex_pc),
         lifetime_start_(kNoLifetime),
         lifetime_end_(kNoLifetime),
-        try_catch_information_(nullptr) {}
+        try_catch_information_(nullptr) {
+    predecessors_.reserve(kDefaultNumberOfPredecessors);
+    successors_.reserve(kDefaultNumberOfSuccessors);
+    dominated_blocks_.reserve(kDefaultNumberOfDominatedBlocks);
+  }
 
-  const GrowableArray<HBasicBlock*>& GetPredecessors() const {
+  const ArenaVector<HBasicBlock*>& GetPredecessors() const {
     return predecessors_;
   }
 
-  const GrowableArray<HBasicBlock*>& GetSuccessors() const {
+  HBasicBlock* GetPredecessor(size_t pred_idx) const {
+    DCHECK_LT(pred_idx, predecessors_.size());
+    return predecessors_[pred_idx];
+  }
+
+  const ArenaVector<HBasicBlock*>& GetSuccessors() const {
     return successors_;
   }
 
-  const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
+  HBasicBlock* GetSuccessor(size_t succ_idx) const {
+    DCHECK_LT(succ_idx, successors_.size());
+    return successors_[succ_idx];
+  }
+
+  bool HasSuccessor(const HBasicBlock* block, size_t start_from = 0u) {
+    return ContainsElement(successors_, block, start_from);
+  }
+
+  const ArenaVector<HBasicBlock*>& GetDominatedBlocks() const {
     return dominated_blocks_;
   }
 
@@ -686,18 +706,16 @@
 
   HBasicBlock* GetDominator() const { return dominator_; }
   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
-  void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
-  void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); }
-  void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
-    for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
-      if (dominated_blocks_.Get(i) == existing) {
-        dominated_blocks_.Put(i, new_block);
-        return;
-      }
-    }
-    LOG(FATAL) << "Unreachable";
-    UNREACHABLE();
+  void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.push_back(block); }
+
+  void RemoveDominatedBlock(HBasicBlock* block) {
+    RemoveElement(dominated_blocks_, block);
   }
+
+  void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
+    ReplaceElement(dominated_blocks_, existing, new_block);
+  }
+
   void ClearDominanceInformation();
 
   int NumberOfBackEdges() const {
@@ -712,24 +730,22 @@
   const HInstructionList& GetPhis() const { return phis_; }
 
   void AddSuccessor(HBasicBlock* block) {
-    successors_.Add(block);
-    block->predecessors_.Add(this);
+    successors_.push_back(block);
+    block->predecessors_.push_back(this);
   }
 
   void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
     size_t successor_index = GetSuccessorIndexOf(existing);
-    DCHECK_NE(successor_index, static_cast<size_t>(-1));
     existing->RemovePredecessor(this);
-    new_block->predecessors_.Add(this);
-    successors_.Put(successor_index, new_block);
+    new_block->predecessors_.push_back(this);
+    successors_[successor_index] = new_block;
   }
 
   void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
     size_t predecessor_index = GetPredecessorIndexOf(existing);
-    DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
     existing->RemoveSuccessor(this);
-    new_block->successors_.Add(this);
-    predecessors_.Put(predecessor_index, new_block);
+    new_block->successors_.push_back(this);
+    predecessors_[predecessor_index] = new_block;
   }
 
   // Insert `this` between `predecessor` and `successor. This method
@@ -737,85 +753,69 @@
   // `predecessor` and `successor`.
   void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
     size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
-    DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
     size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
-    DCHECK_NE(successor_index, static_cast<size_t>(-1));
-    successor->predecessors_.Put(predecessor_index, this);
-    predecessor->successors_.Put(successor_index, this);
-    successors_.Add(successor);
-    predecessors_.Add(predecessor);
+    successor->predecessors_[predecessor_index] = this;
+    predecessor->successors_[successor_index] = this;
+    successors_.push_back(successor);
+    predecessors_.push_back(predecessor);
   }
 
   void RemovePredecessor(HBasicBlock* block) {
-    predecessors_.Delete(block);
+    predecessors_.erase(predecessors_.begin() + GetPredecessorIndexOf(block));
   }
 
   void RemoveSuccessor(HBasicBlock* block) {
-    successors_.Delete(block);
+    successors_.erase(successors_.begin() + GetSuccessorIndexOf(block));
   }
 
   void ClearAllPredecessors() {
-    predecessors_.Reset();
+    predecessors_.clear();
   }
 
   void AddPredecessor(HBasicBlock* block) {
-    predecessors_.Add(block);
-    block->successors_.Add(this);
+    predecessors_.push_back(block);
+    block->successors_.push_back(this);
   }
 
   void SwapPredecessors() {
-    DCHECK_EQ(predecessors_.Size(), 2u);
-    HBasicBlock* temp = predecessors_.Get(0);
-    predecessors_.Put(0, predecessors_.Get(1));
-    predecessors_.Put(1, temp);
+    DCHECK_EQ(predecessors_.size(), 2u);
+    std::swap(predecessors_[0], predecessors_[1]);
   }
 
   void SwapSuccessors() {
-    DCHECK_EQ(successors_.Size(), 2u);
-    HBasicBlock* temp = successors_.Get(0);
-    successors_.Put(0, successors_.Get(1));
-    successors_.Put(1, temp);
+    DCHECK_EQ(successors_.size(), 2u);
+    std::swap(successors_[0], successors_[1]);
   }
 
   size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const {
-    for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
-      if (predecessors_.Get(i) == predecessor) {
-        return i;
-      }
-    }
-    return -1;
+    return IndexOfElement(predecessors_, predecessor);
   }
 
   size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
-    for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
-      if (successors_.Get(i) == successor) {
-        return i;
-      }
-    }
-    return -1;
+    return IndexOfElement(successors_, successor);
   }
 
   HBasicBlock* GetSinglePredecessor() const {
-    DCHECK_EQ(GetPredecessors().Size(), 1u);
-    return GetPredecessors().Get(0);
+    DCHECK_EQ(GetPredecessors().size(), 1u);
+    return GetPredecessor(0);
   }
 
   HBasicBlock* GetSingleSuccessor() const {
-    DCHECK_EQ(GetSuccessors().Size(), 1u);
-    return GetSuccessors().Get(0);
+    DCHECK_EQ(GetSuccessors().size(), 1u);
+    return GetSuccessor(0);
   }
 
   // Returns whether the first occurrence of `predecessor` in the list of
   // predecessors is at index `idx`.
   bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const {
-    DCHECK_EQ(GetPredecessors().Get(idx), predecessor);
+    DCHECK_EQ(GetPredecessor(idx), predecessor);
     return GetPredecessorIndexOf(predecessor) == idx;
   }
 
   // Returns the number of non-exceptional successors. SsaChecker ensures that
   // these are stored at the beginning of the successor list.
   size_t NumberOfNormalSuccessors() const {
-    return EndsWithTryBoundary() ? 1 : GetSuccessors().Size();
+    return EndsWithTryBoundary() ? 1 : GetSuccessors().size();
   }
 
   // Split the block into two blocks just before `cursor`. Returns the newly
@@ -880,8 +880,7 @@
 
   bool IsLoopPreHeaderFirstPredecessor() const {
     DCHECK(IsLoopHeader());
-    DCHECK(!GetPredecessors().IsEmpty());
-    return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
+    return GetPredecessor(0) == GetLoopInformation()->GetPreHeader();
   }
 
   HLoopInformation* GetLoopInformation() const {
@@ -952,13 +951,13 @@
 
  private:
   HGraph* graph_;
-  GrowableArray<HBasicBlock*> predecessors_;
-  GrowableArray<HBasicBlock*> successors_;
+  ArenaVector<HBasicBlock*> predecessors_;
+  ArenaVector<HBasicBlock*> successors_;
   HInstructionList instructions_;
   HInstructionList phis_;
   HLoopInformation* loop_information_;
   HBasicBlock* dominator_;
-  GrowableArray<HBasicBlock*> dominated_blocks_;
+  ArenaVector<HBasicBlock*> dominated_blocks_;
   int block_id_;
   // The dex program counter of the first instruction of this block.
   const uint32_t dex_pc_;
@@ -2268,11 +2267,11 @@
   bool IsControlFlow() const OVERRIDE { return true; }
 
   HBasicBlock* IfTrueSuccessor() const {
-    return GetBlock()->GetSuccessors().Get(0);
+    return GetBlock()->GetSuccessor(0);
   }
 
   HBasicBlock* IfFalseSuccessor() const {
-    return GetBlock()->GetSuccessors().Get(1);
+    return GetBlock()->GetSuccessor(1);
   }
 
   DECLARE_INSTRUCTION(If);
@@ -2300,14 +2299,13 @@
   bool IsControlFlow() const OVERRIDE { return true; }
 
   // Returns the block's non-exceptional successor (index zero).
-  HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors().Get(0); }
+  HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessor(0); }
 
   // Returns whether `handler` is among its exception handlers (non-zero index
   // successors).
   bool HasExceptionHandler(const HBasicBlock& handler) const {
     DCHECK(handler.IsCatchBlock());
-    return GetBlock()->GetSuccessors().Contains(
-        const_cast<HBasicBlock*>(&handler), /* start_from */ 1);
+    return GetBlock()->HasSuccessor(&handler, 1u /* Skip first successor. */);
   }
 
   // If not present already, adds `handler` to its block's list of exception
@@ -2337,8 +2335,8 @@
   explicit HExceptionHandlerIterator(const HTryBoundary& try_boundary)
     : block_(*try_boundary.GetBlock()), index_(block_.NumberOfNormalSuccessors()) {}
 
-  bool Done() const { return index_ == block_.GetSuccessors().Size(); }
-  HBasicBlock* Current() const { return block_.GetSuccessors().Get(index_); }
+  bool Done() const { return index_ == block_.GetSuccessors().size(); }
+  HBasicBlock* Current() const { return block_.GetSuccessor(index_); }
   size_t CurrentSuccessorIndex() const { return index_; }
   void Advance() { ++index_; }
 
diff --git a/compiler/optimizing/pretty_printer.h b/compiler/optimizing/pretty_printer.h
index 934514e..34850a5 100644
--- a/compiler/optimizing/pretty_printer.h
+++ b/compiler/optimizing/pretty_printer.h
@@ -71,23 +71,23 @@
   void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
     PrintString("BasicBlock ");
     PrintInt(block->GetBlockId());
-    const GrowableArray<HBasicBlock*>& predecessors = block->GetPredecessors();
-    if (!predecessors.IsEmpty()) {
+    const ArenaVector<HBasicBlock*>& predecessors = block->GetPredecessors();
+    if (!predecessors.empty()) {
       PrintString(", pred: ");
-      for (size_t i = 0; i < predecessors.Size() -1; i++) {
-        PrintInt(predecessors.Get(i)->GetBlockId());
+      for (size_t i = 0; i < predecessors.size() -1; i++) {
+        PrintInt(predecessors[i]->GetBlockId());
         PrintString(", ");
       }
-      PrintInt(predecessors.Peek()->GetBlockId());
+      PrintInt(predecessors.back()->GetBlockId());
     }
-    const GrowableArray<HBasicBlock*>& successors = block->GetSuccessors();
-    if (!successors.IsEmpty()) {
+    const ArenaVector<HBasicBlock*>& successors = block->GetSuccessors();
+    if (!successors.empty()) {
       PrintString(", succ: ");
-      for (size_t i = 0; i < successors.Size() - 1; i++) {
-        PrintInt(successors.Get(i)->GetBlockId());
+      for (size_t i = 0; i < successors.size() - 1; i++) {
+        PrintInt(successors[i]->GetBlockId());
         PrintString(", ");
       }
-      PrintInt(successors.Peek()->GetBlockId());
+      PrintInt(successors.back()->GetBlockId());
     }
     PrintNewLine();
     HGraphVisitor::VisitBasicBlock(block);
@@ -131,7 +131,7 @@
     PrintString("  ");
     PrintInt(gota->GetId());
     PrintString(": Goto ");
-    PrintInt(current_block_->GetSuccessors().Get(0)->GetBlockId());
+    PrintInt(current_block_->GetSuccessor(0)->GetBlockId());
     PrintNewLine();
   }
 
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 37c8bc5..6f1f6af 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -1212,14 +1212,13 @@
    * moves in B3.
    */
   if (block_from->GetDominator() != nullptr) {
-    const GrowableArray<HBasicBlock*>& dominated = block_from->GetDominator()->GetDominatedBlocks();
-    for (size_t i = 0; i < dominated.Size(); ++i) {
-      size_t position = dominated.Get(i)->GetLifetimeStart();
+    for (HBasicBlock* dominated : block_from->GetDominator()->GetDominatedBlocks()) {
+      size_t position = dominated->GetLifetimeStart();
       if ((position > from) && (block_to->GetLifetimeStart() > position)) {
         // Even if we found a better block, we continue iterating in case
         // a dominated block is closer.
         // Note that dominated blocks are not sorted in liveness order.
-        block_to = dominated.Get(i);
+        block_to = dominated;
         DCHECK_NE(block_to, block_from);
       }
     }
@@ -1498,7 +1497,7 @@
   DCHECK(IsValidDestination(destination)) << destination;
   if (source.Equals(destination)) return;
 
-  DCHECK_EQ(block->GetSuccessors().Size(), 1u);
+  DCHECK_EQ(block->GetSuccessors().size(), 1u);
   HInstruction* last = block->GetLastInstruction();
   // We insert moves at exit for phi predecessors and connecting blocks.
   // A block ending with an if cannot branch to a block with phis because
@@ -1725,13 +1724,13 @@
 
   // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
   // we need to put the moves at the entry of `to`.
-  if (from->GetSuccessors().Size() == 1) {
+  if (from->GetSuccessors().size() == 1) {
     InsertParallelMoveAtExitOf(from,
                                interval->GetParent()->GetDefinedBy(),
                                source->ToLocation(),
                                destination->ToLocation());
   } else {
-    DCHECK_EQ(to->GetPredecessors().Size(), 1u);
+    DCHECK_EQ(to->GetPredecessors().size(), 1u);
     InsertParallelMoveAtEntryOf(to,
                                 interval->GetParent()->GetDefinedBy(),
                                 source->ToLocation(),
@@ -1833,8 +1832,8 @@
     for (uint32_t idx : live->Indexes()) {
       HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
       LiveInterval* interval = current->GetLiveInterval();
-      for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
-        ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
+      for (HBasicBlock* predecessor : block->GetPredecessors()) {
+        ConnectSplitSiblings(interval, predecessor, block);
       }
     }
   }
@@ -1844,9 +1843,9 @@
     HBasicBlock* current = it.Current();
     for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
       HInstruction* phi = inst_it.Current();
-      for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
-        HBasicBlock* predecessor = current->GetPredecessors().Get(i);
-        DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
+      for (size_t i = 0, e = current->GetPredecessors().size(); i < e; ++i) {
+        HBasicBlock* predecessor = current->GetPredecessor(i);
+        DCHECK_EQ(predecessor->GetSuccessors().size(), 1u);
         HInstruction* input = phi->InputAt(i);
         Location source = input->GetLiveInterval()->GetLocationAt(
             predecessor->GetLifetimeEnd() - 1);
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 561c3b4..e6209b9 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -241,8 +241,8 @@
     HBasicBlock* block = loop_headers_.Get(i);
     for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
       HPhi* phi = it.Current()->AsPhi();
-      for (size_t pred = 0; pred < block->GetPredecessors().Size(); pred++) {
-        HInstruction* input = ValueOfLocal(block->GetPredecessors().Get(pred), phi->GetRegNumber());
+      for (HBasicBlock* predecessor : block->GetPredecessors()) {
+        HInstruction* input = ValueOfLocal(predecessor, phi->GetRegNumber());
         phi->AddInput(input);
       }
     }
@@ -369,16 +369,16 @@
     // Save the loop header so that the last phase of the analysis knows which
     // blocks need to be updated.
     loop_headers_.Add(block);
-  } else if (block->GetPredecessors().Size() > 0) {
+  } else if (block->GetPredecessors().size() > 0) {
     // All predecessors have already been visited because we are visiting in reverse post order.
     // We merge the values of all locals, creating phis if those values differ.
     for (size_t local = 0; local < current_locals_->Size(); local++) {
       bool one_predecessor_has_no_value = false;
       bool is_different = false;
-      HInstruction* value = ValueOfLocal(block->GetPredecessors().Get(0), local);
+      HInstruction* value = ValueOfLocal(block->GetPredecessor(0), local);
 
-      for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
-        HInstruction* current = ValueOfLocal(block->GetPredecessors().Get(i), local);
+      for (HBasicBlock* predecessor : block->GetPredecessors()) {
+        HInstruction* current = ValueOfLocal(predecessor, local);
         if (current == nullptr) {
           one_predecessor_has_no_value = true;
           break;
@@ -395,9 +395,9 @@
 
       if (is_different) {
         HPhi* phi = new (GetGraph()->GetArena()) HPhi(
-            GetGraph()->GetArena(), local, block->GetPredecessors().Size(), Primitive::kPrimVoid);
-        for (size_t i = 0; i < block->GetPredecessors().Size(); i++) {
-          HInstruction* pred_value = ValueOfLocal(block->GetPredecessors().Get(i), local);
+            GetGraph()->GetArena(), local, block->GetPredecessors().size(), Primitive::kPrimVoid);
+        for (size_t i = 0; i < block->GetPredecessors().size(); i++) {
+          HInstruction* pred_value = ValueOfLocal(block->GetPredecessor(i), local);
           phi->SetRawInputAt(i, pred_value);
         }
         block->AddPhi(phi);
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 40502c1..0c1831b 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -73,7 +73,7 @@
   forward_predecessors.SetSize(graph_->GetBlocks().Size());
   for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
-    size_t number_of_forward_predecessors = block->GetPredecessors().Size();
+    size_t number_of_forward_predecessors = block->GetPredecessors().size();
     if (block->IsLoopHeader()) {
       number_of_forward_predecessors -= block->GetLoopInformation()->NumberOfBackEdges();
     }
@@ -89,8 +89,7 @@
   do {
     HBasicBlock* current = worklist.Pop();
     graph_->linear_order_.Add(current);
-    for (size_t i = 0, e = current->GetSuccessors().Size(); i < e; ++i) {
-      HBasicBlock* successor = current->GetSuccessors().Get(i);
+    for (HBasicBlock* successor : current->GetSuccessors()) {
       int block_id = successor->GetBlockId();
       size_t number_of_remaining_predecessors = forward_predecessors.Get(block_id);
       if (number_of_remaining_predecessors == 1) {
@@ -185,8 +184,7 @@
 
     // Set phi inputs of successors of this block corresponding to this block
     // as live_in.
-    for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
-      HBasicBlock* successor = block->GetSuccessors().Get(i);
+    for (HBasicBlock* successor : block->GetSuccessors()) {
       live_in->Union(GetLiveInSet(*successor));
       size_t phi_input_index = successor->GetPredecessorIndexOf(block);
       for (HInstructionIterator inst_it(successor->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
@@ -296,8 +294,7 @@
   BitVector* live_out = GetLiveOutSet(block);
   bool changed = false;
   // The live_out set of a block is the union of live_in sets of its successors.
-  for (size_t i = 0, e = block.GetSuccessors().Size(); i < e; ++i) {
-    HBasicBlock* successor = block.GetSuccessors().Get(i);
+  for (HBasicBlock* successor : block.GetSuccessors()) {
     if (live_out->Union(GetLiveInSet(*successor))) {
       changed = true;
     }
@@ -342,8 +339,8 @@
     // will avoid a move between the two blocks.
     HBasicBlock* block = liveness.GetBlockFromPosition(GetStart() / 2);
     size_t next_register_use = FirstRegisterUse();
-    for (size_t i = 0; i < block->GetPredecessors().Size(); ++i) {
-      size_t position = block->GetPredecessors().Get(i)->GetLifetimeEnd() - 1;
+    for (HBasicBlock* predecessor : block->GetPredecessors()) {
+      size_t position = predecessor->GetLifetimeEnd() - 1;
       // We know positions above GetStart() do not have a location yet.
       if (position < GetStart()) {
         LiveInterval* existing = GetParent()->GetSiblingAt(position);
@@ -376,17 +373,16 @@
             return reg;
           }
         }
-        const GrowableArray<HBasicBlock*>& predecessors = user->GetBlock()->GetPredecessors();
         // If the instruction dies at the phi assignment, we can try having the
         // same register.
-        if (end == predecessors.Get(input_index)->GetLifetimeEnd()) {
+        if (end == user->GetBlock()->GetPredecessor(input_index)->GetLifetimeEnd()) {
           for (size_t i = 0, e = user->InputCount(); i < e; ++i) {
             if (i == input_index) {
               continue;
             }
             HInstruction* input = user->InputAt(i);
             Location location = input->GetLiveInterval()->GetLocationAt(
-                predecessors.Get(i)->GetLifetimeEnd() - 1);
+                user->GetBlock()->GetPredecessor(i)->GetLifetimeEnd() - 1);
             if (location.IsRegisterKind()) {
               int reg = RegisterOrLowRegister(location);
               if (free_until[reg] >= use_position) {
@@ -420,10 +416,11 @@
 int LiveInterval::FindHintAtDefinition() const {
   if (defined_by_->IsPhi()) {
     // Try to use the same register as one of the inputs.
-    const GrowableArray<HBasicBlock*>& predecessors = defined_by_->GetBlock()->GetPredecessors();
+    const ArenaVector<HBasicBlock*>& predecessors = defined_by_->GetBlock()->GetPredecessors();
     for (size_t i = 0, e = defined_by_->InputCount(); i < e; ++i) {
       HInstruction* input = defined_by_->InputAt(i);
-      size_t end = predecessors.Get(i)->GetLifetimeEnd();
+      DCHECK_LT(i, predecessors.size());
+      size_t end = predecessors[i]->GetLifetimeEnd();
       LiveInterval* input_interval = input->GetLiveInterval()->GetSiblingAt(end - 1);
       if (input_interval->GetEnd() == end) {
         // If the input dies at the end of the predecessor, we know its register can
diff --git a/compiler/optimizing/suspend_check_test.cc b/compiler/optimizing/suspend_check_test.cc
index 5ca66a1..e745d94 100644
--- a/compiler/optimizing/suspend_check_test.cc
+++ b/compiler/optimizing/suspend_check_test.cc
@@ -36,7 +36,7 @@
   bool graph_built = builder.BuildGraph(*item);
   ASSERT_TRUE(graph_built);
 
-  HBasicBlock* first_block = graph->GetEntryBlock()->GetSuccessors().Get(0);
+  HBasicBlock* first_block = graph->GetEntryBlock()->GetSuccessor(0);
   HInstruction* first_instruction = first_block->GetFirstInstruction();
   // Account for some tests having a store local as first instruction.
   ASSERT_TRUE(first_instruction->IsSuspendCheck()
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index 3a4bccd..a36b0fb 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -52,13 +52,14 @@
   "SSA2Dalvik   ",
   "Dalvik2SSA   ",
   "DebugInfo    ",
-  "Successor    ",
   "RegAlloc     ",
   "Data         ",
-  "Preds        ",
   "STL          ",
   "Graph        ",
   "BasicBlock   ",
+  "Predecessors ",
+  "Successors   ",
+  "Dominated    ",
   "Instruction  ",
   "LoopInfo     ",
   "TryCatchInf  ",
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index af2bfbc..47defb4 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -62,13 +62,14 @@
   kArenaAllocSSAToDalvikMap,
   kArenaAllocDalvikToSSAMap,
   kArenaAllocDebugInfo,
-  kArenaAllocSuccessor,
   kArenaAllocRegAlloc,
   kArenaAllocData,
-  kArenaAllocPredecessors,
   kArenaAllocSTL,
   kArenaAllocGraph,
   kArenaAllocBasicBlock,
+  kArenaAllocPredecessors,
+  kArenaAllocSuccessors,
+  kArenaAllocDominated,
   kArenaAllocInstruction,
   kArenaAllocLoopInfo,
   kArenaAllocTryCatchInfo,