Use ScopedArenaAllocator for CacheFieldLoweringInfo pass.

Change-Id: Idcc2edeb865e29b1bc42b108fc58a1f964295317
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index d159f49..667ee26 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -1095,16 +1095,15 @@
 }
 
 void MIRGraph::DoCacheFieldLoweringInfo() {
-  // Try to use stack-allocated array, resort to heap if we exceed the initial size.
-  static constexpr size_t kInitialSize = 32;
-  uint16_t stack_idxs[kInitialSize];
-  UniquePtr<uint16_t[]> allocated_idxs;
-  uint16_t* field_idxs = stack_idxs;
-  size_t size = kInitialSize;
+  // All IGET/IPUT/SGET/SPUT instructions take 2 code units and there must also be a RETURN.
+  const uint32_t max_refs = (current_code_item_->insns_size_in_code_units_ - 1u) / 2u;
+  ScopedArenaAllocator allocator(&cu_->arena_stack);
+  uint16_t* field_idxs =
+      reinterpret_cast<uint16_t*>(allocator.Alloc(max_refs * sizeof(uint16_t), kArenaAllocMisc));
 
   // Find IGET/IPUT/SGET/SPUT insns, store IGET/IPUT fields at the beginning, SGET/SPUT at the end.
   size_t ifield_pos = 0u;
-  size_t sfield_pos = size;
+  size_t sfield_pos = max_refs;
   AllNodesIterator iter(this);
   for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
     if (bb->block_type != kDalvikByteCode) {
@@ -1113,14 +1112,12 @@
     for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
       if (mir->dalvikInsn.opcode >= Instruction::IGET &&
           mir->dalvikInsn.opcode <= Instruction::SPUT_SHORT) {
-        bool need_alloc = false;
         const Instruction* insn = Instruction::At(current_code_item_->insns_ + mir->offset);
-        uint16_t field_idx;
         // Get field index and try to find it among existing indexes. If found, it's usually among
         // the last few added, so we'll start the search from ifield_pos/sfield_pos. Though this
         // is a linear search, it actually performs much better than map based approach.
         if (mir->dalvikInsn.opcode <= Instruction::IPUT_SHORT) {
-          field_idx = insn->VRegC_22c();
+          uint16_t field_idx = insn->VRegC_22c();
           size_t i = ifield_pos;
           while (i != 0u && field_idxs[i - 1] != field_idx) {
             --i;
@@ -1129,44 +1126,18 @@
             mir->meta.ifield_lowering_info = i - 1;
           } else {
             mir->meta.ifield_lowering_info = ifield_pos;
-            if (UNLIKELY(ifield_pos == sfield_pos)) {
-              need_alloc = true;
-            } else {
-              field_idxs[ifield_pos++] = field_idx;
-            }
+            field_idxs[ifield_pos++] = field_idx;
           }
         } else {
-          field_idx = insn->VRegB_21c();
+          uint16_t field_idx = insn->VRegB_21c();
           size_t i = sfield_pos;
-          while (i != size && field_idxs[i] != field_idx) {
+          while (i != max_refs && field_idxs[i] != field_idx) {
             ++i;
           }
-          if (i != size) {
-            mir->meta.sfield_lowering_info = size - i - 1u;
+          if (i != max_refs) {
+            mir->meta.sfield_lowering_info = max_refs - i - 1u;
           } else {
-            mir->meta.sfield_lowering_info = size - sfield_pos;
-            if (UNLIKELY(ifield_pos == sfield_pos)) {
-              need_alloc = true;
-            } else {
-              field_idxs[--sfield_pos] = field_idx;
-            }
-          }
-        }
-        if (UNLIKELY(need_alloc)) {
-          DCHECK(field_idxs == stack_idxs);
-          // All IGET/IPUT/SGET/SPUT instructions take 2 code units and there must also be a RETURN.
-          uint32_t max_refs = (current_code_item_->insns_size_in_code_units_ - 1u) / 2u;
-          allocated_idxs.reset(new uint16_t[max_refs]);
-          field_idxs = allocated_idxs.get();
-          size_t sfield_count = size - sfield_pos;
-          sfield_pos = max_refs - sfield_count;
-          size = max_refs;
-          memcpy(field_idxs, stack_idxs, ifield_pos * sizeof(field_idxs[0]));
-          memcpy(field_idxs + sfield_pos, stack_idxs + ifield_pos,
-                 sfield_count * sizeof(field_idxs[0]));
-          if (mir->dalvikInsn.opcode <= Instruction::IPUT_SHORT) {
-            field_idxs[ifield_pos++] = field_idx;
-          } else {
+            mir->meta.sfield_lowering_info = max_refs - sfield_pos;
             field_idxs[--sfield_pos] = field_idx;
           }
         }
@@ -1186,16 +1157,16 @@
                                 ifield_lowering_infos_.GetRawStorage(), ifield_pos);
   }
 
-  if (sfield_pos != size) {
+  if (sfield_pos != max_refs) {
     // Resolve static field infos.
     DCHECK_EQ(sfield_lowering_infos_.Size(), 0u);
-    sfield_lowering_infos_.Resize(size - sfield_pos);
-    for (size_t pos = size; pos != sfield_pos;) {
+    sfield_lowering_infos_.Resize(max_refs - sfield_pos);
+    for (size_t pos = max_refs; pos != sfield_pos;) {
       --pos;
       sfield_lowering_infos_.Insert(MirSFieldLoweringInfo(field_idxs[pos]));
     }
     MirSFieldLoweringInfo::Resolve(cu_->compiler_driver, GetCurrentDexCompilationUnit(),
-                                sfield_lowering_infos_.GetRawStorage(), size - sfield_pos);
+                                sfield_lowering_infos_.GetRawStorage(), max_refs - sfield_pos);
   }
 }
 
diff --git a/compiler/dex/mir_field_info.h b/compiler/dex/mir_field_info.h
index 41cb4ce..e64e9fc 100644
--- a/compiler/dex/mir_field_info.h
+++ b/compiler/dex/mir_field_info.h
@@ -100,7 +100,7 @@
 class MirIFieldLoweringInfo : public MirFieldInfo {
  public:
   // For each requested instance field retrieve the field's declaring location (dex file, class
-  // index and field index) and volatility and compute the whether we can fast path the access
+  // index and field index) and volatility and compute whether we can fast path the access
   // with IGET/IPUT. For fast path fields, retrieve the field offset.
   static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
                       MirIFieldLoweringInfo* field_infos, size_t count)
@@ -143,7 +143,7 @@
 class MirSFieldLoweringInfo : public MirFieldInfo {
  public:
   // For each requested static field retrieve the field's declaring location (dex file, class
-  // index and field index) and volatility and compute the whether we can fast path the access with
+  // index and field index) and volatility and compute whether we can fast path the access with
   // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
   // the field access, i.e. the field offset, whether the field is in the same class as the
   // method being compiled, whether the declaring class can be safely assumed to be initialized