Sharpen virtual calls to final methods.

Also remove unused instance resolution stub.

Change-Id: I2abb988d107e98ac0148fb81464b22622a468382
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 700174e..ecf33ac 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1339,12 +1339,30 @@
   // Special case to get oat code without overwriting a trampoline.
   CHECK(method->GetDeclaringClass()->IsInitializing());
   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
-  // method for direct methods.
-  CHECK(method->IsStatic() || method->IsDirect());
-  ClassHelper kh(method->GetDeclaringClass());
+  // method for direct methods (or virtual methods made direct).
+  Class* declaring_class = method->GetDeclaringClass();
+  size_t oat_method_index;
+  if (method->IsStatic() || method->IsDirect()) {
+    // Simple case where the oat method index was stashed at load time.
+    oat_method_index = method->GetMethodIndex();
+  } else {
+    // We're invoking a virtual method directly (thanks to sharpening), compute the oat_method_index
+    // by search for its position in the declared virtual methods.
+    oat_method_index = declaring_class->NumDirectMethods();
+    size_t end = declaring_class->NumVirtualMethods();
+    bool found = false;
+    for (size_t i = 0; i < end; i++) {
+      oat_method_index++;
+      if (declaring_class->GetVirtualMethod(i) == method) {
+        found = true;
+        break;
+      }
+    }
+    CHECK(found) << "Didn't find oat method index for virtual method: " << PrettyMethod(method);
+  }
+  ClassHelper kh(declaring_class);
   UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(kh.GetDexFile(), kh.GetDescriptor()));
-  size_t method_index = method->GetMethodIndex();
-  return oat_class->GetOatMethod(method_index).GetCode();
+  return oat_class->GetOatMethod(oat_method_index).GetCode();
 }
 
 void ClassLinker::FixupStaticTrampolines(Class* klass) {
@@ -1470,25 +1488,26 @@
     // TODO: append direct methods to class object
     klass->SetVirtualMethods(AllocObjectArray<Method>(it.NumVirtualMethods()));
   }
-  size_t method_index = 0;
+  size_t class_def_method_index = 0;
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
     SirtRef<Method> method(AllocMethod());
     klass->SetDirectMethod(i, method.get());
     LoadMethod(dex_file, it, klass, method);
     if (oat_class.get() != NULL) {
-      LinkCode(method, oat_class.get(), method_index);
+      LinkCode(method, oat_class.get(), class_def_method_index);
     }
-    method->SetMethodIndex(method_index);
-    method_index++;
+    method->SetMethodIndex(class_def_method_index);
+    class_def_method_index++;
   }
   for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
     SirtRef<Method> method(AllocMethod());
     klass->SetVirtualMethod(i, method.get());
     LoadMethod(dex_file, it, klass, method);
+    DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
     if (oat_class.get() != NULL) {
-      LinkCode(method, oat_class.get(), method_index);
+      LinkCode(method, oat_class.get(), class_def_method_index);
     }
-    method_index++;
+    class_def_method_index++;
   }
   DCHECK(!it.HasNext());
 }