Mark newly allocated objects as precise.

New-arrays were previously precise because of finality. Because this has been
weakened we need to explicitly mark allocated arrays as precise.
Fix RegTypeCache::FromUninitialized that was not making newly allocated objects
precise if the class wasn't final. As the object is being allocated we can be
sure of its preciseness.
For core, increases type based interface devirtualization from 0.136% to 2.873%
(21x improvement) and general devirtualization from 1.874% to 4.663% (2.5x
improvement).

Change-Id: I494c5b4de7227bd5c8ca9cf37399594182dcd6f8
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 6338659..efdd6f6 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -2882,8 +2882,7 @@
   }
 }
 
-void MethodVerifier::VerifyNewArray(const Instruction* inst, bool is_filled,
-                                    bool is_range) {
+void MethodVerifier::VerifyNewArray(const Instruction* inst, bool is_filled, bool is_range) {
   uint32_t type_idx;
   if (!is_filled) {
     DCHECK_EQ(inst->Opcode(), Instruction::NEW_ARRAY);
@@ -2906,7 +2905,8 @@
       /* make sure "size" register is valid type */
       work_line_->VerifyRegisterType(inst->VRegB_22c(), reg_types_.Integer());
       /* set register type to array class */
-      work_line_->SetRegisterType(inst->VRegA_22c(), res_type);
+      const RegType& precise_type = reg_types_.FromUninitialized(res_type);
+      work_line_->SetRegisterType(inst->VRegA_22c(), precise_type);
     } else {
       // Verify each register. If "arg_count" is bad, VerifyRegisterType() will run off the end of
       // the list and fail. It's legal, if silly, for arg_count to be zero.
@@ -2924,7 +2924,8 @@
         }
       }
       // filled-array result goes into "result" register
-      work_line_->SetResultRegisterType(res_type);
+      const RegType& precise_type = reg_types_.FromUninitialized(res_type);
+      work_line_->SetResultRegisterType(precise_type);
     }
   }
 }
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index ce3e6f6..6013250 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -377,7 +377,6 @@
     entry = new UnresolvedReferenceType(descriptor.c_str(), entries_.size());
   } else {
     mirror::Class* klass = uninit_type.GetClass();
-    DCHECK(!klass->IsArrayClass());
     if(uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
       // For uninitialized "this reference" look for reference types that are not precise.
       for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -387,32 +386,18 @@
         }
       }
       entry = new ReferenceType(klass, "", entries_.size());
-    } else {
-      if (klass->IsFinal()) {
-        if (klass->IsInstantiable()) {
-          for (size_t i = primitive_count_; i < entries_.size(); i++) {
-            RegType* cur_entry = entries_[i];
-            if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
-              return *cur_entry;
-            }
-          }
-          // Precise type was not found , create one !
-          entry = new PreciseReferenceType(klass, "", entries_.size());
-        } else {
-          return Conflict();
+    } else if (klass->IsInstantiable()) {
+      // We're uninitialized because of allocation, look or create a precise type as allocations
+      // may only create objects of that type.
+      for (size_t i = primitive_count_; i < entries_.size(); i++) {
+        RegType* cur_entry = entries_[i];
+        if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
+          return *cur_entry;
         }
-      } else {
-        // Not a final class, create an imprecise reference. Look up if we have it in the cache
-        // first.
-        for (size_t i = primitive_count_; i < entries_.size(); i++) {
-          RegType* cur_entry = entries_[i];
-          if (cur_entry->IsReference() && !(cur_entry->IsPrecise()) &&
-              cur_entry->GetClass() == klass) {
-            return *cur_entry;
-          }
-        }
-        entry = new ReferenceType(klass, "", entries_.size());
       }
+      entry = new PreciseReferenceType(klass, uninit_type.GetDescriptor(), entries_.size());
+    } else {
+      return Conflict();
     }
  }
   entries_.push_back(entry);
@@ -447,8 +432,7 @@
     mirror::Class* klass = type.GetClass();
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
       RegType* cur_entry = entries_[i];
-      if (cur_entry->IsUninitializedThisReference() &&
-          cur_entry->GetClass() == klass) {
+      if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
         return *cur_entry;
       }
     }