Inline field and method resolution.

According to profiling results, field and method resolutions are hot points
during interpreter execution. This CL attempts to speed up these resolutions.

Forces aggressive inlining of FindFieldFromCode and FindMethodFromCode. This
allows to reduce the overhead of access check code when the interpreter runs
without these checks. Templatize these functions to optimize inlining and their
callers.

Also spread the use of C++11 "nullptr" in place of "NULL" in field access and
invoke helpers.

Change-Id: Ic1a69834d8975b2cddcddaae32f08a7de146a951
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