JNI: Inline fast-path for `JniMethodStart()`.

Golem results for art-opt-cc (higher is better):
linux-ia32                       before after
NativeDowncallStaticNormal       35.306 47.382 (+34.20%)
NativeDowncallStaticNormal6      32.951 42.247 (+28.21%)
NativeDowncallStaticNormalRefs6  17.866 41.355 (+131.5%)
NativeDowncallVirtualNormal      35.341 46.836 (+32.53%)
NativeDowncallVirtualNormal6     32.403 41.791 (+28.97%)
NativeDowncallVirtualNormalRefs6 32.131 40.500 (+26.05%)
linux-x64                        before after
NativeDowncallStaticNormal       33.350 43.716 (+31.08%)
NativeDowncallStaticNormal6      31.096 43.176 (+38.85%)
NativeDowncallStaticNormalRefs6  30.617 38.500 (+25.75%)
NativeDowncallVirtualNormal      33.234 43.672 (+32.41%)
NativeDowncallVirtualNormal6     30.617 42.247 (+37.98%)
NativeDowncallVirtualNormalRefs6 32.131 42.701 (+32.90%)
linux-armv7                      before after
NativeDowncallStaticNormal       7.8701 9.9651 (+26.62%)
NativeDowncallStaticNormal6      7.4147 8.9463 (+20.66%)
NativeDowncallStaticNormalRefs6  6.8830 8.3868 (+21.85%)
NativeDowncallVirtualNormal      7.8316 9.8377 (+25.61%)
NativeDowncallVirtualNormal6     7.4147 9.3596 (+26.23%)
NativeDowncallVirtualNormalRefs6 6.6794 8.4325 (+26.25%)
linux-armv8                      before after
NativeDowncallStaticNormal       7.6372 9.8571 (+29.07%)
NativeDowncallStaticNormal6      7.4147 9.4905 (+28.00%)
NativeDowncallStaticNormalRefs6  6.8527 8.6705 (+26.53%)
NativeDowncallVirtualNormal      7.4147 9.3183 (+25.67%)
NativeDowncallVirtualNormal6     7.0755 9.2593 (+30.86%)
NativeDowncallVirtualNormalRefs6 6.5604 8.2967 (+26.47%)

Note that NativeDowncallStaticNormalRefs6 on x86 has been
jumping like crazy since
    https://android-review.googlesource.com/1905055
between ~17.6 and ~32.4 for completely unrelated changes,
so if we take the 32.4 as a baseline, the improvement is
only ~27.6% in line with the other x86 benchmarks.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: run-gtests.sh
Test: testrunner.py --target --optimizing
Bug: 172332525
Change-Id: I771a4765bd3a7c4e58b94be4155515241ea6fa3c
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index a222ff3..8de5c9c 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -27,6 +27,7 @@
 #include "common_compiler_test.h"
 #include "compiler.h"
 #include "dex/dex_file.h"
+#include "entrypoints/entrypoint_utils-inl.h"
 #include "gtest/gtest.h"
 #include "indirect_reference_table.h"
 #include "java_frame_root_info.h"
@@ -337,6 +338,8 @@
   static jobject jobj_;
   static jobject class_loader_;
 
+  static void AssertCallerObjectLocked(JNIEnv* env);
+
   static LockWord GetLockWord(jobject obj);
 
  protected:
@@ -391,53 +394,17 @@
   jmethodID jmethod_;
 
  private:
-  // Helper class that overrides original entrypoints with alternative versions
-  // that check that the object (`this` or class) is locked.
-  class ScopedSynchronizedEntryPointOverrides {
-   public:
-    ScopedSynchronizedEntryPointOverrides() {
-      QuickEntryPoints* qpoints = &Thread::Current()->tlsPtr_.quick_entrypoints;
-      jni_method_start_original_ = qpoints->pJniMethodStart;
-      qpoints->pJniMethodStart = JniMethodStartSynchronizedOverride;
-      jni_method_end_original_ = qpoints->pJniMethodEnd;
-      qpoints->pJniMethodEnd = JniMethodEndSynchronizedOverride;
-      jni_method_end_with_reference_original_ = qpoints->pJniMethodEndWithReference;
-      qpoints->pJniMethodEndWithReference = JniMethodEndWithReferenceSynchronizedOverride;
-    }
-
-    ~ScopedSynchronizedEntryPointOverrides() {
-      QuickEntryPoints* qpoints = &Thread::Current()->tlsPtr_.quick_entrypoints;
-      qpoints->pJniMethodStart = jni_method_start_original_;
-      qpoints->pJniMethodEnd = jni_method_end_original_;
-      qpoints->pJniMethodEndWithReference = jni_method_end_with_reference_original_;
-    }
-  };
-
-  static void AssertCallerObjectLocked(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void JniMethodStartSynchronizedOverride(Thread* self);
-  static void JniMethodEndSynchronizedOverride(Thread* self);
-  static mirror::Object* JniMethodEndWithReferenceSynchronizedOverride(
-      jobject result, Thread* self);
-
-  using JniStartType = void (*)(Thread*);
-  using JniEndType = void (*)(Thread*);
-  using JniEndWithReferenceType = mirror::Object* (*)(jobject, Thread*);
-
-  static JniStartType jni_method_start_original_;
-  static JniEndType jni_method_end_original_;
-  static JniEndWithReferenceType jni_method_end_with_reference_original_;
-
   bool check_generic_jni_;
 };
 
 jclass JniCompilerTest::jklass_;
 jobject JniCompilerTest::jobj_;
 jobject JniCompilerTest::class_loader_;
-JniCompilerTest::JniStartType JniCompilerTest::jni_method_start_original_;
-JniCompilerTest::JniEndType JniCompilerTest::jni_method_end_original_;
-JniCompilerTest::JniEndWithReferenceType JniCompilerTest::jni_method_end_with_reference_original_;
 
-void JniCompilerTest::AssertCallerObjectLocked(Thread* self) {
+void JniCompilerTest::AssertCallerObjectLocked(JNIEnv* env) {
+  Thread* self = down_cast<JNIEnvExt*>(env)->GetSelf();
+  CHECK_EQ(self, Thread::Current());
+  ScopedObjectAccess soa(self);
   ArtMethod** caller_frame = self->GetManagedStack()->GetTopQuickFrame();
   CHECK(caller_frame != nullptr);
   ArtMethod* caller = *caller_frame;
@@ -447,7 +414,10 @@
   CHECK(!caller->IsCriticalNative());
   CHECK(caller->IsSynchronized());
   ObjPtr<mirror::Object> lock;
-  if (caller->IsStatic()) {
+  if (self->GetManagedStack()->GetTopQuickFrameTag()) {
+    // Generic JNI.
+    lock = GetGenericJniSynchronizationObject(self, caller);
+  } else if (caller->IsStatic()) {
     lock = caller->GetDeclaringClass();
   } else {
     uint8_t* sp = reinterpret_cast<uint8_t*>(caller_frame);
@@ -461,23 +431,6 @@
   CHECK_EQ(Monitor::GetLockOwnerThreadId(lock), self->GetThreadId());
 }
 
-void JniCompilerTest::JniMethodStartSynchronizedOverride(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
-  AssertCallerObjectLocked(self);
-  jni_method_start_original_(self);
-}
-
-void JniCompilerTest::JniMethodEndSynchronizedOverride(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
-  jni_method_end_original_(self);
-  AssertCallerObjectLocked(self);
-}
-
-mirror::Object* JniCompilerTest::JniMethodEndWithReferenceSynchronizedOverride(
-    jobject result, Thread* self) NO_THREAD_SAFETY_ANALYSIS {
-  mirror::Object* raw_result = jni_method_end_with_reference_original_(result, self);
-  AssertCallerObjectLocked(self);
-  return raw_result;
-}
-
 LockWord JniCompilerTest::GetLockWord(jobject obj) {
   ScopedObjectAccess soa(Thread::Current());
   return soa.Decode<mirror::Object>(obj)->GetLockWord(/*as_volatile=*/ false);
@@ -886,7 +839,8 @@
 }
 
 int gJava_MyClassNatives_fooJJ_synchronized_calls[kJniKindCount] = {};
-jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv*, jobject, jlong x, jlong y) {
+jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject, jlong x, jlong y) {
+  JniCompilerTest::AssertCallerObjectLocked(env);
   gJava_MyClassNatives_fooJJ_synchronized_calls[gCurrentJni]++;
   return x | y;
 }
@@ -894,7 +848,6 @@
 void JniCompilerTest::CompileAndRun_fooJJ_synchronizedImpl() {
   SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_fooJJ_synchronized));
-  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls[gCurrentJni]);
   jlong a = 0x1000000020000000ULL;
@@ -1220,7 +1173,8 @@
 JNI_TEST(CompileAndRunStaticIntObjectObjectMethod)
 
 int gJava_MyClassNatives_fooSSIOO_calls[kJniKindCount] = {};
-jobject Java_MyClassNatives_fooSSIOO(JNIEnv*, jclass klass, jint x, jobject y, jobject z) {
+jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
+  JniCompilerTest::AssertCallerObjectLocked(env);
   gJava_MyClassNatives_fooSSIOO_calls[gCurrentJni]++;
   switch (x) {
     case 1:
@@ -1236,7 +1190,6 @@
   SetUpForTest(true, "fooSSIOO",
                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_fooSSIOO));
-  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls[gCurrentJni]);
   jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, nullptr, nullptr);
@@ -1505,7 +1458,8 @@
 JNI_TEST(GetText)
 
 int gJava_MyClassNatives_GetSinkProperties_calls[kJniKindCount] = {};
-jarray Java_MyClassNatives_GetSinkProperties(JNIEnv*, jobject thisObj, jstring s) {
+jarray Java_MyClassNatives_GetSinkProperties(JNIEnv* env, jobject thisObj, jstring s) {
+  JniCompilerTest::AssertCallerObjectLocked(env);
   EXPECT_EQ(s, nullptr);
   gJava_MyClassNatives_GetSinkProperties_calls[gCurrentJni]++;
 
@@ -1518,7 +1472,6 @@
 void JniCompilerTest::GetSinkPropertiesNativeImpl() {
   SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
                CURRENT_JNI_WRAPPER(Java_MyClassNatives_GetSinkProperties));
-  ScopedSynchronizedEntryPointOverrides ssepo;
 
   EXPECT_EQ(0, gJava_MyClassNatives_GetSinkProperties_calls[gCurrentJni]);
   jarray result = down_cast<jarray>(