Supporting de-virtualization for precise types.

Sharpening invoke-virtual and invoke-interface calls to invoke-direct for cases
where the type of "this" pointer in the invoke- params is precisely known.

Instructions that have an invoke opcode are marked as interesting, for each invoke-virtual/interface
we come across with a precise type for "this" we mark the location as a candidate for sharpening,
resolve the concrete method and save its method reference <DexFile, DexMethodIndex> to be sharpened
in CompilerDriver::ComputeInvokeInfo().

Added a new entry to AOT statistics showing the percentage of sharpened calls that were based on
type analysis.

Fix a minor bug in type creation for GetSuperClass(). Previously super class of a precise reference
had precise types created which is not necessarily the case.

Fixed DCHECK in Class::FindVirtualMethodForVirtual to handle cases for Miranda methods.

Sharpening only takes place for cases where no soft failures happen at verification time.

Change-Id: Ic027d0226d6f95260c1918014cb6313f2e0ca455
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 8e23b74..7153768 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -179,7 +179,7 @@
 
     //To pass the verification, the type should be imprecise,
     // instantiable or an interface with the precise type set to false.
-    CHECK(!precise || klass->IsInstantiable());
+    DCHECK(!precise || klass->IsInstantiable());
 
     // Create a precise type if:
     // 1- Class is final and NOT an interface. a precise interface
@@ -189,10 +189,9 @@
     RegType* entry;
     // 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());
+      DCHECK(!(klass->IsAbstract()) || klass->IsArrayClass());
+      DCHECK(!klass->IsInterface());
       entry = new PreciseReferenceType(klass, descriptor, entries_.size());
-
     } else {
       entry = new ReferenceType(klass, descriptor, entries_.size());
     }
@@ -372,7 +371,7 @@
         return *cur_entry;
       }
     }
-    std::string descriptor = "";
+    std::string descriptor("");
     entry = new UninitialisedReferenceType(klass, descriptor, allocation_pc, entries_.size());
   }
   entries_.push_back(entry);
@@ -401,17 +400,34 @@
           return *cur_entry;
         }
       }
-      std::string descriptor = "";
+      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;
+        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, descriptor, entries_.size());
+          } else {
+            return Conflict();
+          }
+      } 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, descriptor, entries_.size());
       }
-      std::string descriptor = "";
-      entry = new PreciseReferenceType(klass, descriptor, entries_.size());
     }
  }
   entries_.push_back(entry);
@@ -447,7 +463,7 @@
         return *cur_entry;
       }
     }
-    std::string descriptor = "";
+    std::string descriptor("");
     entry = new UninitialisedThisReferenceType(klass, descriptor, entries_.size());
   }
   entries_.push_back(entry);