Fix bugs in type precision.

Fix bugs in type precision.

Don't create precise type for interfaces.

Class objects that are final and Abstract are only valid for Array Types. Added check for that.

Don't create a precise type from an uninitialized this reference type. Bug caused creating Precise
types for Abstract classes.

Change-Id: Ic7671d5587cb531f7d949d8fee8b88fd554252fa
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index a8caa94..8e23b74 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -177,20 +177,22 @@
     }
     // Class was not found, must create new type.
 
-    // Create a type if:
-    // 1-The class is instantiable ( not Abstract or Interface ), we should
-    //   abort failing the verification if we get that.
-    // 2- And, the class should be instantiable (Not interface, Abstract or a
-    //    primitive type) OR it is imprecise.
-
-    // Create a precise type if :
-    // 1-The class is final.
-    // 2-OR the precise was passed as true .
+    //To pass the verification, the type should be imprecise,
+    // instantiable or an interface with the precise type set to false.
     CHECK(!precise || klass->IsInstantiable());
+
+    // Create a precise type if:
+    // 1- Class is final and NOT an interface. a precise interface
+    //    is meaningless !!
+    // 2- Precise Flag passed as true.
+
     RegType* entry;
-    // Create an imprecise type if we can'tt tell for a fact that it is precise.
-    if (klass->IsFinal() || precise) {
+    // Create an imprecise type if we can't tell for a fact that it is precise.
+    if ((klass->IsFinal()) || precise) {
+      CHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
+      CHECK(!klass->IsInterface());
       entry = new PreciseReferenceType(klass, descriptor, entries_.size());
+
     } else {
       entry = new ReferenceType(klass, descriptor, entries_.size());
     }
@@ -378,6 +380,7 @@
 }
 const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
   RegType* entry;
+
   if (uninit_type.IsUnresolvedTypes()) {
     std::string descriptor(uninit_type.GetDescriptor());
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -390,15 +393,27 @@
     entry = new UnresolvedReferenceType(descriptor, entries_.size());
   } else {
     mirror::Class* klass = uninit_type.GetClass();
-    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;
+    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++) {
+        RegType* cur_entry = entries_[i];
+        if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+          return *cur_entry;
+        }
       }
+      std::string descriptor = "";
+      entry = new ReferenceType(klass, descriptor, entries_.size());
+    } else {
+      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;
+        }
+      }
+      std::string descriptor = "";
+      entry = new PreciseReferenceType(klass, descriptor, entries_.size());
     }
-    std::string descriptor = "";
-    entry = new PreciseReferenceType(klass, descriptor, entries_.size());
-  }
+ }
   entries_.push_back(entry);
   return *entry;
 }