Bring Reference Type Propagation to NewArray

Change-Id: Ieff4f38854e06b0ed4b5689ced94a4289053d80d
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index 163458f..48090a3 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -647,7 +647,7 @@
   graph->AddBlock(block);
   entry->AddSuccessor(block);
   HInstruction* new_array = new (allocator)
-      HNewArray(constant_10, 0, Primitive::kPrimInt, kQuickAllocArray);
+      HNewArray(constant_10, 0, Primitive::kPrimInt, graph->GetDexFile(), kQuickAllocArray);
   block->AddInstruction(new_array);
   block->AddInstruction(new (allocator) HGoto());
 
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 49a0444..c4f033d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1027,7 +1027,11 @@
   QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
       ? kQuickAllocArrayWithAccessCheck
       : kQuickAllocArray;
-  HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint);
+  HInstruction* object = new (arena_) HNewArray(length,
+                                                dex_pc,
+                                                type_index,
+                                                *dex_compilation_unit_->GetDexFile(),
+                                                entrypoint);
   current_block_->AddInstruction(object);
 
   const char* descriptor = dex_file_->StringByTypeIdx(type_index);
@@ -1993,8 +1997,8 @@
       QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
           ? kQuickAllocArrayWithAccessCheck
           : kQuickAllocArray;
-      current_block_->AddInstruction(
-          new (arena_) HNewArray(length, dex_pc, type_index, entrypoint));
+      current_block_->AddInstruction(new (arena_) HNewArray(
+          length, dex_pc, type_index, *dex_compilation_unit_->GetDexFile(), entrypoint));
       UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
       break;
     }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 01870c3..a44d745 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2656,16 +2656,19 @@
   HNewArray(HInstruction* length,
             uint32_t dex_pc,
             uint16_t type_index,
+            const DexFile& dex_file,
             QuickEntrypointEnum entrypoint)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         dex_pc_(dex_pc),
         type_index_(type_index),
+        dex_file_(dex_file),
         entrypoint_(entrypoint) {
     SetRawInputAt(0, length);
   }
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
   uint16_t GetTypeIndex() const { return type_index_; }
+  const DexFile& GetDexFile() const { return dex_file_; }
 
   // Calls runtime so needs an environment.
   bool NeedsEnvironment() const OVERRIDE { return true; }
@@ -2682,6 +2685,7 @@
  private:
   const uint32_t dex_pc_;
   const uint16_t type_index_;
+  const DexFile& dex_file_;
   const QuickEntrypointEnum entrypoint_;
 
   DISALLOW_COPY_AND_ASSIGN(HNewArray);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 601b48a..91b2e6f 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -35,7 +35,7 @@
 
 void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
   // TODO: handle other instructions that give type info
-  // (NewArray/Call/Field accesses/array accesses)
+  // (Call/Field accesses/array accesses)
 
   // Initialize exact types first for faster convergence.
   for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
@@ -44,6 +44,8 @@
       VisitNewInstance(instr->AsNewInstance());
     } else if (instr->IsLoadClass()) {
       VisitLoadClass(instr->AsLoadClass());
+    } else if (instr->IsNewArray()) {
+      VisitNewArray(instr->AsNewArray());
     }
   }
 
@@ -159,18 +161,29 @@
   }
 }
 
-void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr,
+                                                       uint16_t type_idx,
+                                                       const DexFile& dex_file) {
+  DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
+
   ScopedObjectAccess soa(Thread::Current());
-  mirror::DexCache* dex_cache =
-      Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
+  mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
   // Get type from dex cache assuming it was populated by the verifier.
-  mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
+  mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
   if (resolved_class != nullptr) {
     MutableHandle<mirror::Class> handle = handles_->NewHandle(resolved_class);
     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
   }
 }
 
+void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
+void ReferenceTypePropagation::VisitNewArray(HNewArray* instr) {
+  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
 void ReferenceTypePropagation::VisitLoadClass(HLoadClass* instr) {
   ScopedObjectAccess soa(Thread::Current());
   mirror::DexCache* dex_cache =
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index b68fc67..12c3362 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -42,6 +42,7 @@
  private:
   void VisitNewInstance(HNewInstance* new_instance);
   void VisitLoadClass(HLoadClass* load_class);
+  void VisitNewArray(HNewArray* instr);
   void VisitPhi(HPhi* phi);
   void VisitBasicBlock(HBasicBlock* block);
 
@@ -50,6 +51,7 @@
 
   void BoundTypeForIfNotNull(HBasicBlock* block);
   void BoundTypeForIfInstanceOf(HBasicBlock* block);
+  void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file);
 
   void ProcessWorklist();
   void AddToWorklist(HInstruction* instr);