Merge "Inline field and method resolution." into dalvik-dev
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index d9c9e31..24ab1ce 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -96,201 +96,6 @@
   return mirror::Array::AllocInstrumented(self, klass, component_count);
 }
 
-mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
-                                 Thread* self, FindFieldType type, size_t expected_size,
-                                 bool access_check) {
-  bool is_primitive;
-  bool is_set;
-  bool is_static;
-  switch (type) {
-    case InstanceObjectRead:     is_primitive = false; is_set = false; is_static = false; break;
-    case InstanceObjectWrite:    is_primitive = false; is_set = true;  is_static = false; break;
-    case InstancePrimitiveRead:  is_primitive = true;  is_set = false; is_static = false; break;
-    case InstancePrimitiveWrite: is_primitive = true;  is_set = true;  is_static = false; break;
-    case StaticObjectRead:       is_primitive = false; is_set = false; is_static = true;  break;
-    case StaticObjectWrite:      is_primitive = false; is_set = true;  is_static = true;  break;
-    case StaticPrimitiveRead:    is_primitive = true;  is_set = false; is_static = true;  break;
-    case StaticPrimitiveWrite:   // Keep GCC happy by having a default handler, fall-through.
-    default:                     is_primitive = true;  is_set = true;  is_static = true;  break;
-  }
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
-  if (UNLIKELY(resolved_field == NULL)) {
-    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
-    return NULL;  // Failure.
-  }
-  mirror::Class* fields_class = resolved_field->GetDeclaringClass();
-  if (access_check) {
-    if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
-      ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
-      return NULL;
-    }
-    mirror::Class* referring_class = referrer->GetDeclaringClass();
-    if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
-                 !referring_class->CanAccessMember(fields_class,
-                                                   resolved_field->GetAccessFlags()))) {
-      // The referring class can't access the resolved field, this may occur as a result of a
-      // protected field being made public by a sub-class. Resort to the dex file to determine
-      // the correct class for the access check.
-      const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
-      fields_class = class_linker->ResolveType(dex_file,
-                                               dex_file.GetFieldId(field_idx).class_idx_,
-                                               referring_class);
-      if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
-        ThrowIllegalAccessErrorClass(referring_class, fields_class);
-        return NULL;  // failure
-      } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
-                                                            resolved_field->GetAccessFlags()))) {
-        ThrowIllegalAccessErrorField(referring_class, resolved_field);
-        return NULL;  // failure
-      }
-    }
-    if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
-      ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
-      return NULL;  // failure
-    } else {
-      FieldHelper fh(resolved_field);
-      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
-                   fh.FieldSize() != expected_size)) {
-        ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-        DCHECK(throw_location.GetMethod() == referrer);
-        self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
-                                 "Attempted read of %zd-bit %s on field '%s'",
-                                 expected_size * (32 / sizeof(int32_t)),
-                                 is_primitive ? "primitive" : "non-primitive",
-                                 PrettyField(resolved_field, true).c_str());
-        return NULL;  // failure
-      }
-    }
-  }
-  if (!is_static) {
-    // instance fields must be being accessed on an initialized class
-    return resolved_field;
-  } else {
-    // If the class is initialized we're done.
-    if (fields_class->IsInitialized()) {
-      return resolved_field;
-    } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
-      // Otherwise let's ensure the class is initialized before resolving the field.
-      return resolved_field;
-    } else {
-      DCHECK(self->IsExceptionPending());  // Throw exception and unwind
-      return NULL;  // failure
-    }
-  }
-}
-
-// Slow path method resolution
-mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
-                                           mirror::ArtMethod* referrer,
-                                           Thread* self, bool access_check, InvokeType type) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  bool is_direct = type == kStatic || type == kDirect;
-  mirror::ArtMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
-  if (UNLIKELY(resolved_method == NULL)) {
-    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
-    return NULL;  // Failure.
-  } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
-    // Maintain interpreter-like semantics where NullPointerException is thrown
-    // after potential NoSuchMethodError from class linker.
-    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-    DCHECK(referrer == throw_location.GetMethod());
-    ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type);
-    return NULL;  // Failure.
-  } else {
-    if (!access_check) {
-      if (is_direct) {
-        return resolved_method;
-      } else if (type == kInterface) {
-        mirror::ArtMethod* interface_method =
-            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
-        if (UNLIKELY(interface_method == NULL)) {
-          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
-                                                                     referrer);
-          return NULL;  // Failure.
-        } else {
-          return interface_method;
-        }
-      } else {
-        mirror::ObjectArray<mirror::ArtMethod>* vtable;
-        uint16_t vtable_index = resolved_method->GetMethodIndex();
-        if (type == kSuper) {
-          vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
-        } else {
-          vtable = this_object->GetClass()->GetVTable();
-        }
-        // TODO: eliminate bounds check?
-        return vtable->Get(vtable_index);
-      }
-    } else {
-      // Incompatible class change should have been handled in resolve method.
-      if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
-        ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
-                                          referrer);
-        return NULL;  // Failure.
-      }
-      mirror::Class* methods_class = resolved_method->GetDeclaringClass();
-      mirror::Class* referring_class = referrer->GetDeclaringClass();
-      if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
-                   !referring_class->CanAccessMember(methods_class,
-                                                     resolved_method->GetAccessFlags()))) {
-        // The referring class can't access the resolved method, this may occur as a result of a
-        // protected method being made public by implementing an interface that re-declares the
-        // method public. Resort to the dex file to determine the correct class for the access check
-        const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
-        methods_class = class_linker->ResolveType(dex_file,
-                                                  dex_file.GetMethodId(method_idx).class_idx_,
-                                                  referring_class);
-        if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
-          ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
-                                                        referrer, resolved_method, type);
-          return NULL;  // Failure.
-        } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
-                                                              resolved_method->GetAccessFlags()))) {
-          ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
-          return NULL;  // Failure.
-        }
-      }
-      if (is_direct) {
-        return resolved_method;
-      } else if (type == kInterface) {
-        mirror::ArtMethod* interface_method =
-            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
-        if (UNLIKELY(interface_method == NULL)) {
-          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
-                                                                     referrer);
-          return NULL;  // Failure.
-        } else {
-          return interface_method;
-        }
-      } else {
-        mirror::ObjectArray<mirror::ArtMethod>* vtable;
-        uint16_t vtable_index = resolved_method->GetMethodIndex();
-        if (type == kSuper) {
-          mirror::Class* super_class = referring_class->GetSuperClass();
-          if (LIKELY(super_class != NULL)) {
-            vtable = referring_class->GetSuperClass()->GetVTable();
-          } else {
-            vtable = NULL;
-          }
-        } else {
-          vtable = this_object->GetClass()->GetVTable();
-        }
-        if (LIKELY(vtable != NULL &&
-                   vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
-          return vtable->GetWithoutChecks(vtable_index);
-        } else {
-          // Behavior to agree with that of the verifier.
-          MethodHelper mh(resolved_method);
-          ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
-                                 mh.GetSignature());
-          return NULL;  // Failure.
-        }
-      }
-    }
-  }
-}
-
 void ThrowStackOverflowError(Thread* self) {
   if (self->IsHandlingStackOverflow()) {
       LOG(ERROR) << "Recursive stack overflow.";
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index c32a661..2008604 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -178,11 +178,235 @@
   StaticPrimitiveWrite,
 };
 
-// Slow field find that can initialize classes and may throw exceptions.
-extern mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
-                                           Thread* self, FindFieldType type, size_t expected_size,
-                                           bool access_check)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+template<FindFieldType type, bool access_check>
+static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
+                                                  Thread* self, size_t expected_size) {
+  bool is_primitive;
+  bool is_set;
+  bool is_static;
+  switch (type) {
+    case InstanceObjectRead:     is_primitive = false; is_set = false; is_static = false; break;
+    case InstanceObjectWrite:    is_primitive = false; is_set = true;  is_static = false; break;
+    case InstancePrimitiveRead:  is_primitive = true;  is_set = false; is_static = false; break;
+    case InstancePrimitiveWrite: is_primitive = true;  is_set = true;  is_static = false; break;
+    case StaticObjectRead:       is_primitive = false; is_set = false; is_static = true;  break;
+    case StaticObjectWrite:      is_primitive = false; is_set = true;  is_static = true;  break;
+    case StaticPrimitiveRead:    is_primitive = true;  is_set = false; is_static = true;  break;
+    case StaticPrimitiveWrite:   // Keep GCC happy by having a default handler, fall-through.
+    default:                     is_primitive = true;  is_set = true;  is_static = true;  break;
+  }
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
+  if (UNLIKELY(resolved_field == nullptr)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
+    return nullptr;  // Failure.
+  }
+  mirror::Class* fields_class = resolved_field->GetDeclaringClass();
+  if (access_check) {
+    if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
+      ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
+      return nullptr;
+    }
+    mirror::Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
+                 !referring_class->CanAccessMember(fields_class,
+                                                   resolved_field->GetAccessFlags()))) {
+      // The referring class can't access the resolved field, this may occur as a result of a
+      // protected field being made public by a sub-class. Resort to the dex file to determine
+      // the correct class for the access check.
+      const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
+      fields_class = class_linker->ResolveType(dex_file,
+                                               dex_file.GetFieldId(field_idx).class_idx_,
+                                               referring_class);
+      if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
+        ThrowIllegalAccessErrorClass(referring_class, fields_class);
+        return nullptr;  // failure
+      } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
+                                                            resolved_field->GetAccessFlags()))) {
+        ThrowIllegalAccessErrorField(referring_class, resolved_field);
+        return nullptr;  // failure
+      }
+    }
+    if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
+      ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
+      return nullptr;  // failure
+    } else {
+      FieldHelper fh(resolved_field);
+      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+                   fh.FieldSize() != expected_size)) {
+        ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+        DCHECK(throw_location.GetMethod() == referrer);
+        self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
+                                 "Attempted read of %zd-bit %s on field '%s'",
+                                 expected_size * (32 / sizeof(int32_t)),
+                                 is_primitive ? "primitive" : "non-primitive",
+                                 PrettyField(resolved_field, true).c_str());
+        return nullptr;  // failure
+      }
+    }
+  }
+  if (!is_static) {
+    // instance fields must be being accessed on an initialized class
+    return resolved_field;
+  } else {
+    // If the class is initialized we're done.
+    if (LIKELY(fields_class->IsInitialized())) {
+      return resolved_field;
+    } else if (LIKELY(class_linker->EnsureInitialized(fields_class, true, true))) {
+      // Otherwise let's ensure the class is initialized before resolving the field.
+      return resolved_field;
+    } else {
+      DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+      return nullptr;  // failure
+    }
+  }
+}
+
+// Explicit template declarations of FindFieldFromCode for all field access types.
+#define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \
+template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \
+static mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
+                                                                 const mirror::ArtMethod* referrer, \
+                                                                 Thread* self, size_t expected_size) \
+
+#define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
+    EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, false); \
+    EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, true)
+
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectRead);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstanceObjectWrite);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveRead);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(InstancePrimitiveWrite);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectRead);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticObjectWrite);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveRead);
+EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(StaticPrimitiveWrite);
+
+#undef EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL
+#undef EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL
+
+template<InvokeType type, bool access_check>
+static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
+                                                    mirror::ArtMethod* referrer, Thread* self) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  mirror::ArtMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
+  if (UNLIKELY(resolved_method == nullptr)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
+    return nullptr;  // Failure.
+  } else if (UNLIKELY(this_object == nullptr && type != kStatic)) {
+    // Maintain interpreter-like semantics where NullPointerException is thrown
+    // after potential NoSuchMethodError from class linker.
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    DCHECK(referrer == throw_location.GetMethod());
+    ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type);
+    return nullptr;  // Failure.
+  } else if (access_check) {
+    // Incompatible class change should have been handled in resolve method.
+    if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
+      ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
+                                        referrer);
+      return nullptr;  // Failure.
+    }
+    mirror::Class* methods_class = resolved_method->GetDeclaringClass();
+    mirror::Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+                 !referring_class->CanAccessMember(methods_class,
+                                                   resolved_method->GetAccessFlags()))) {
+      // The referring class can't access the resolved method, this may occur as a result of a
+      // protected method being made public by implementing an interface that re-declares the
+      // method public. Resort to the dex file to determine the correct class for the access check
+      const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      methods_class = class_linker->ResolveType(dex_file,
+                                                dex_file.GetMethodId(method_idx).class_idx_,
+                                                referring_class);
+      if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
+        ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
+                                                      referrer, resolved_method, type);
+        return nullptr;  // Failure.
+      } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
+                                                            resolved_method->GetAccessFlags()))) {
+        ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
+        return nullptr;  // Failure.
+      }
+    }
+  }
+  switch (type) {
+    case kStatic:
+    case kDirect:
+      return resolved_method;
+    case kVirtual: {
+      mirror::ObjectArray<mirror::ArtMethod>* vtable = this_object->GetClass()->GetVTable();
+      uint16_t vtable_index = resolved_method->GetMethodIndex();
+      if (access_check &&
+          (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength()))) {
+        // Behavior to agree with that of the verifier.
+        MethodHelper mh(resolved_method);
+        ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
+                               mh.GetSignature());
+        return nullptr;  // Failure.
+      }
+      DCHECK(vtable != nullptr);
+      return vtable->GetWithoutChecks(vtable_index);
+    }
+    case kSuper: {
+      mirror::Class* super_class = referrer->GetDeclaringClass()->GetSuperClass();
+      uint16_t vtable_index = resolved_method->GetMethodIndex();
+      mirror::ObjectArray<mirror::ArtMethod>* vtable;
+      if (access_check) {
+        // Check existence of super class.
+        vtable = (super_class != nullptr) ? super_class->GetVTable() : nullptr;
+        if (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength())) {
+          // Behavior to agree with that of the verifier.
+          MethodHelper mh(resolved_method);
+          ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
+                                 mh.GetSignature());
+          return nullptr;  // Failure.
+        }
+      } else {
+        // Super class must exist.
+        DCHECK(super_class != nullptr);
+        vtable = super_class->GetVTable();
+      }
+      DCHECK(vtable != nullptr);
+      return vtable->GetWithoutChecks(vtable_index);
+    }
+    case kInterface: {
+      mirror::ArtMethod* interface_method =
+          this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+      if (UNLIKELY(interface_method == nullptr)) {
+        ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
+                                                                   referrer);
+        return nullptr;  // Failure.
+      } else {
+        return interface_method;
+      }
+    }
+    default:
+      LOG(FATAL) << "Unknown invoke type " << type;
+      return nullptr;  // Failure.
+  }
+}
+
+// Explicit template declarations of FindMethodFromCode for all invoke types.
+#define EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, _access_check)                        \
+  template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE                              \
+  static mirror::ArtMethod* FindMethodFromCode<_type, _access_check>(uint32_t method_idx,         \
+                                                                     mirror::Object* this_object, \
+                                                                     mirror::ArtMethod* referrer, \
+                                                                     Thread* self)
+#define EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
+    EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, false);   \
+    EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, true)
+
+EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kStatic);
+EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kDirect);
+EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kVirtual);
+EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kSuper);
+EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface);
+
+#undef EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL
+#undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
 static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
@@ -282,11 +506,6 @@
   }
 }
 
-extern mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
-                                             mirror::ArtMethod* referrer,
-                                             Thread* self, bool access_check, InvokeType type)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
 static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
                                                     const mirror::ArtMethod* referrer,
                                                     Thread* self, bool can_run_clinit,
diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc
index bd6f795..095e99e 100644
--- a/runtime/entrypoints/portable/portable_field_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_field_entrypoints.cc
@@ -33,12 +33,8 @@
     field->Set32(field->GetDeclaringClass(), new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx,
-                            referrer,
-                            Thread::Current(),
-                            StaticPrimitiveWrite,
-                            sizeof(uint32_t),
-                            true);
+  field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, Thread::Current(),
+                                                        sizeof(uint32_t));
   if (LIKELY(field != NULL)) {
     field->Set32(field->GetDeclaringClass(), new_value);
     return 0;
@@ -55,12 +51,8 @@
     field->Set64(field->GetDeclaringClass(), new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx,
-                            referrer,
-                            Thread::Current(),
-                            StaticPrimitiveWrite,
-                            sizeof(uint64_t),
-                            true);
+  field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, Thread::Current(),
+                                                        sizeof(uint64_t));
   if (LIKELY(field != NULL)) {
     field->Set64(field->GetDeclaringClass(), new_value);
     return 0;
@@ -78,8 +70,8 @@
     field->SetObj(field->GetDeclaringClass(), new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticObjectWrite, sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, Thread::Current(),
+                                                     sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     field->SetObj(field->GetDeclaringClass(), new_value);
     return 0;
@@ -94,8 +86,8 @@
   if (LIKELY(field != NULL)) {
     return field->Get32(field->GetDeclaringClass());
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticPrimitiveRead, sizeof(uint32_t), true);
+  field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, Thread::Current(),
+                                                       sizeof(uint32_t));
   if (LIKELY(field != NULL)) {
     return field->Get32(field->GetDeclaringClass());
   }
@@ -109,8 +101,8 @@
   if (LIKELY(field != NULL)) {
     return field->Get64(field->GetDeclaringClass());
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticPrimitiveRead, sizeof(uint64_t), true);
+  field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, Thread::Current(),
+                                                       sizeof(uint64_t));
   if (LIKELY(field != NULL)) {
     return field->Get64(field->GetDeclaringClass());
   }
@@ -125,8 +117,8 @@
   if (LIKELY(field != NULL)) {
     return field->GetObj(field->GetDeclaringClass());
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticObjectRead, sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, Thread::Current(),
+                                                    sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     return field->GetObj(field->GetDeclaringClass());
   }
@@ -142,8 +134,8 @@
     field->Set32(obj, new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveWrite, sizeof(uint32_t), true);
+  field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, Thread::Current(),
+                                                          sizeof(uint32_t));
   if (LIKELY(field != NULL)) {
     field->Set32(obj, new_value);
     return 0;
@@ -160,8 +152,8 @@
     field->Set64(obj, new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveWrite, sizeof(uint64_t), true);
+  field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, Thread::Current(),
+                                                          sizeof(uint64_t));
   if (LIKELY(field != NULL)) {
     field->Set64(obj, new_value);
     return 0;
@@ -180,8 +172,8 @@
     field->SetObj(obj, new_value);
     return 0;
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstanceObjectWrite, sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, Thread::Current(),
+                                                       sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     field->SetObj(obj, new_value);
     return 0;
@@ -197,8 +189,8 @@
   if (LIKELY(field != NULL)) {
     return field->Get32(obj);
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveRead, sizeof(uint32_t), true);
+  field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, Thread::Current(),
+                                                         sizeof(uint32_t));
   if (LIKELY(field != NULL)) {
     return field->Get32(obj);
   }
@@ -213,8 +205,8 @@
   if (LIKELY(field != NULL)) {
     return field->Get64(obj);
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveRead, sizeof(uint64_t), true);
+  field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, Thread::Current(),
+                                                         sizeof(uint64_t));
   if (LIKELY(field != NULL)) {
     return field->Get64(obj);
   }
@@ -230,8 +222,8 @@
   if (LIKELY(field != NULL)) {
     return field->GetObj(obj);
   }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstanceObjectRead, sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, Thread::Current(),
+                                                      sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     return field->GetObj(obj);
   }
diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
index 14cbd84..e2a0cc2 100644
--- a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
@@ -21,21 +21,13 @@
 
 namespace art {
 
-static mirror::ArtMethod* FindMethodHelper(uint32_t method_idx,
-                                                mirror::Object* this_object,
-                                                mirror::ArtMethod* caller_method,
-                                                bool access_check,
-                                                InvokeType type,
-                                                Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = FindMethodFast(method_idx,
-                                                  this_object,
-                                                  caller_method,
-                                                  access_check,
-                                                  type);
+template<InvokeType type, bool access_check>
+static mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_object,
+                                           mirror::ArtMethod* caller_method, Thread* thread) {
+  mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method,
+                                             access_check, type);
   if (UNLIKELY(method == NULL)) {
-    method = FindMethodFromCode(method_idx, this_object, caller_method,
-                                thread, access_check, type);
+    method = FindMethodFromCode<type, access_check>(method_idx, this_object, caller_method, thread);
     if (UNLIKELY(method == NULL)) {
       CHECK(thread->IsExceptionPending());
       return 0;  // failure
@@ -53,12 +45,32 @@
   return method;
 }
 
+// Explicit template declarations of FindMethodHelper for all invoke types.
+#define EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, _access_check)                               \
+  template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                                \
+  static mirror::ArtMethod* FindMethodHelper<_type, _access_check>(uint32_t method_idx,               \
+                                                                   mirror::Object* this_object,       \
+                                                                   mirror::ArtMethod* caller_method,  \
+                                                                   Thread* thread)
+#define EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(_type) \
+    EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, false);   \
+    EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL(_type, true)
+
+EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kStatic);
+EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kDirect);
+EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kVirtual);
+EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kSuper);
+EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL(kInterface);
+
+#undef EXPLICIT_FIND_METHOD_HELPER_TYPED_TEMPLATE_DECL
+#undef EXPLICIT_FIND_METHOD_HELPER_TEMPLATE_DECL
+
 extern "C" mirror::Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
                                                                                        mirror::Object* this_object,
                                                                                        mirror::ArtMethod* referrer,
                                                                                        Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
+  return FindMethodHelper<kStatic, true>(method_idx, this_object, referrer, thread);
 }
 
 extern "C" mirror::Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
@@ -66,7 +78,7 @@
                                                                                        mirror::ArtMethod* referrer,
                                                                                        Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
+  return FindMethodHelper<kDirect, true>(method_idx, this_object, referrer, thread);
 }
 
 extern "C" mirror::Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
@@ -74,7 +86,7 @@
                                                                                         mirror::ArtMethod* referrer,
                                                                                         Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
+  return FindMethodHelper<kVirtual, true>(method_idx, this_object, referrer, thread);
 }
 
 extern "C" mirror::Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
@@ -82,7 +94,7 @@
                                                                                       mirror::ArtMethod* referrer,
                                                                                       Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
+  return FindMethodHelper<kSuper, true>(method_idx, this_object, referrer, thread);
 }
 
 extern "C" mirror::Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
@@ -90,7 +102,7 @@
                                                                                           mirror::ArtMethod* referrer,
                                                                                           Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
+  return FindMethodHelper<kInterface, true>(method_idx, this_object, referrer, thread);
 }
 
 extern "C" mirror::Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
@@ -98,7 +110,7 @@
                                                                         mirror::ArtMethod* referrer,
                                                                         Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
+  return FindMethodHelper<kInterface, false>(method_idx, this_object, referrer, thread);
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 0ec1eb7..0a533bd 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -35,7 +35,7 @@
     return field->Get32(field->GetDeclaringClass());
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticPrimitiveRead, sizeof(int32_t), true);
+  field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     return field->Get32(field->GetDeclaringClass());
   }
@@ -52,7 +52,7 @@
     return field->Get64(field->GetDeclaringClass());
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticPrimitiveRead, sizeof(int64_t), true);
+  field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     return field->Get64(field->GetDeclaringClass());
   }
@@ -69,8 +69,8 @@
     return field->GetObj(field->GetDeclaringClass());
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticObjectRead, sizeof(mirror::Object*),
-                            true);
+  field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
+                                                    sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     return field->GetObj(field->GetDeclaringClass());
   }
@@ -87,8 +87,8 @@
     return field->Get32(obj);
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveRead, sizeof(int32_t),
-                            true);
+  field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
+                                                         sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -110,8 +110,8 @@
     return field->Get64(obj);
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveRead, sizeof(int64_t),
-                            true);
+  field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
+                                                         sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -134,8 +134,8 @@
     return field->GetObj(obj);
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectRead, sizeof(mirror::Object*),
-                            true);
+  field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
+                                                      sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -158,7 +158,7 @@
     return 0;  // success
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticPrimitiveWrite, sizeof(int32_t), true);
+  field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     field->Set32(field->GetDeclaringClass(), new_value);
     return 0;  // success
@@ -176,7 +176,7 @@
     return 0;  // success
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticPrimitiveWrite, sizeof(int64_t), true);
+  field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     field->Set64(field->GetDeclaringClass(), new_value);
     return 0;  // success
@@ -197,7 +197,8 @@
     }
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, StaticObjectWrite, sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
+                                                     sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     field->SetObj(field->GetDeclaringClass(), new_value);
     return 0;  // success
@@ -216,8 +217,8 @@
     return 0;  // success
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveWrite, sizeof(int32_t),
-                            true);
+  field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
+                                                          sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -244,8 +245,8 @@
   }
   *sp = callee_save;
   self->SetTopOfStack(sp, 0);
-  field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveWrite, sizeof(int64_t),
-                            true);
+  field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
+                                                          sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
@@ -270,8 +271,8 @@
     return 0;  // success
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectWrite,
-                            sizeof(mirror::Object*), true);
+  field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
+                                                       sizeof(mirror::Object*));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
diff --git a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
index 07c1c01..b852a32 100644
--- a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
@@ -118,8 +118,7 @@
       DCHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
       dex_method_idx = instr->VRegB_3rc();
     }
-    method = FindMethodFromCode(dex_method_idx, this_object, caller_method, self,
-                                false, kInterface);
+    method = FindMethodFromCode<kInterface, false>(dex_method_idx, this_object, caller_method, self);
     if (UNLIKELY(method == NULL)) {
       CHECK(self->IsExceptionPending());
       return 0;  // Failure.
@@ -142,17 +141,15 @@
   return result;
 }
 
-
+template<InvokeType type, bool access_check>
 static uint64_t artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
                                 mirror::ArtMethod* caller_method,
-                                Thread* self, mirror::ArtMethod** sp, bool access_check,
-                                InvokeType type)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+                                Thread* self, mirror::ArtMethod** sp) {
   mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method,
                                                   access_check, type);
   if (UNLIKELY(method == NULL)) {
     FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
-    method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
+    method = FindMethodFromCode<type, access_check>(method_idx, this_object, caller_method, self);
     if (UNLIKELY(method == NULL)) {
       CHECK(self->IsExceptionPending());
       return 0;  // failure
@@ -176,6 +173,27 @@
   return result;
 }
 
+// Explicit template declarations of artInvokeCommon for all invoke types.
+#define EXPLICIT_ART_INVOKE_COMMON_TEMPLATE_DECL(_type, _access_check)                        \
+  template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                        \
+  static uint64_t artInvokeCommon<_type, _access_check>(uint32_t method_idx,                  \
+                                                        mirror::Object* this_object,          \
+                                                        mirror::ArtMethod* caller_method,     \
+                                                        Thread* self, mirror::ArtMethod** sp)
+
+#define EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(_type) \
+    EXPLICIT_ART_INVOKE_COMMON_TEMPLATE_DECL(_type, false);   \
+    EXPLICIT_ART_INVOKE_COMMON_TEMPLATE_DECL(_type, true)
+
+EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(kStatic);
+EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(kDirect);
+EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(kVirtual);
+EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(kSuper);
+EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL(kInterface);
+
+#undef EXPLICIT_ART_INVOKE_COMMON_TYPED_TEMPLATE_DECL
+#undef EXPLICIT_ART_INVOKE_COMMON_TEMPLATE_DECL
+
 // See comments in runtime_support_asm.S
 extern "C" uint64_t artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,
                                                                 mirror::Object* this_object,
@@ -183,7 +201,7 @@
                                                                 Thread* self,
                                                                 mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kInterface);
+  return artInvokeCommon<kInterface, true>(method_idx, this_object, caller_method, self, sp);
 }
 
 
@@ -193,7 +211,7 @@
                                                              Thread* self,
                                                              mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kDirect);
+  return artInvokeCommon<kDirect, true>(method_idx, this_object, caller_method, self, sp);
 }
 
 extern "C" uint64_t artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,
@@ -202,7 +220,7 @@
                                                              Thread* self,
                                                              mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kStatic);
+  return artInvokeCommon<kStatic, true>(method_idx, this_object, caller_method, self, sp);
 }
 
 extern "C" uint64_t artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,
@@ -211,7 +229,7 @@
                                                             Thread* self,
                                                             mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kSuper);
+  return artInvokeCommon<kSuper, true>(method_idx, this_object, caller_method, self, sp);
 }
 
 extern "C" uint64_t artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,
@@ -220,7 +238,7 @@
                                                               Thread* self,
                                                               mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kVirtual);
+  return artInvokeCommon<kVirtual, true>(method_idx, this_object, caller_method, self, sp);
 }
 
 }  // namespace art
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 29b00d2..0bc834c 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -90,7 +90,6 @@
 bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
             const Instruction* inst, uint16_t inst_data, JValue* result);
 
-
 // Handles invoke-XXX/range instructions.
 // Returns true on success, otherwise throws an exception and returns false.
 template<InvokeType type, bool is_range, bool do_access_check>
@@ -99,14 +98,14 @@
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
   Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
-  ArtMethod* const method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
-                                               do_access_check, type);
+  ArtMethod* const method = FindMethodFromCode<type, do_access_check>(method_idx, receiver,
+                                                                      shadow_frame.GetMethod(),
+                                                                      self);
   if (type != kStatic) {
     // Reload the vreg since the GC may have moved the object.
     receiver = shadow_frame.GetVRegReference(vregC);
   }
-
-  if (UNLIKELY(method == NULL)) {
+  if (UNLIKELY(method == nullptr)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
     return false;
@@ -128,7 +127,7 @@
                                         JValue* result) {
   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
   Object* const receiver = shadow_frame.GetVRegReference(vregC);
-  if (UNLIKELY(receiver == NULL)) {
+  if (UNLIKELY(receiver == nullptr)) {
     // We lost the reference to the method index so we cannot get a more
     // precised exception message.
     ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
@@ -136,7 +135,7 @@
   }
   const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   ArtMethod* const method = receiver->GetClass()->GetVTable()->GetWithoutChecks(vtable_idx);
-  if (UNLIKELY(method == NULL)) {
+  if (UNLIKELY(method == nullptr)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
     return false;
@@ -155,12 +154,11 @@
 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
 static inline bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
                               const Instruction* inst, uint16_t inst_data) {
-  bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
-  uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
-  ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
-                                  find_type, Primitive::FieldSize(field_type),
-                                  do_access_check);
-  if (UNLIKELY(f == NULL)) {
+  const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
+  const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
+  ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
+                                                              Primitive::FieldSize(field_type));
+  if (UNLIKELY(f == nullptr)) {
     CHECK(self->IsExceptionPending());
     return false;
   }
@@ -169,7 +167,7 @@
     obj = f->GetDeclaringClass();
   } else {
     obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-    if (UNLIKELY(obj == NULL)) {
+    if (UNLIKELY(obj == nullptr)) {
       ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
       return false;
     }
@@ -208,7 +206,7 @@
 template<Primitive::Type field_type>
 static inline bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
   Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-  if (UNLIKELY(obj == NULL)) {
+  if (UNLIKELY(obj == nullptr)) {
     // We lost the reference to the field index so we cannot get a more
     // precised exception message.
     ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
@@ -241,10 +239,9 @@
   bool do_assignability_check = do_access_check;
   bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
   uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
-  ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
-                                  find_type, Primitive::FieldSize(field_type),
-                                  do_access_check);
-  if (UNLIKELY(f == NULL)) {
+  ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
+                                                              Primitive::FieldSize(field_type));
+  if (UNLIKELY(f == nullptr)) {
     CHECK(self->IsExceptionPending());
     return false;
   }
@@ -253,7 +250,7 @@
     obj = f->GetDeclaringClass();
   } else {
     obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-    if (UNLIKELY(obj == NULL)) {
+    if (UNLIKELY(obj == nullptr)) {
       ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
                                               f, false);
       return false;
@@ -281,7 +278,7 @@
       break;
     case Primitive::kPrimNot: {
       Object* reg = shadow_frame.GetVRegReference(vregA);
-      if (do_assignability_check && reg != NULL) {
+      if (do_assignability_check && reg != nullptr) {
         Class* field_class = FieldHelper(f).GetType();
         if (!reg->VerifierInstanceOf(field_class)) {
           // This should never happen.
@@ -308,7 +305,7 @@
 template<Primitive::Type field_type>
 static inline bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
   Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-  if (UNLIKELY(obj == NULL)) {
+  if (UNLIKELY(obj == nullptr)) {
     // We lost the reference to the field index so we cannot get a more
     // precised exception message.
     ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 4c5f90c..6c6d488 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -291,8 +291,8 @@
   ASSERT_TRUE(field_id != NULL);
   uint32_t field_idx = dex_file->GetIndexForFieldId(*field_id);
 
-  ArtField* field = FindFieldFromCode(field_idx, clinit, Thread::Current(), StaticObjectRead,
-                                      sizeof(Object*), true);
+  ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(),
+                                                              sizeof(Object*));
   Object* s0 = field->GetObj(klass);
   EXPECT_TRUE(s0 != NULL);