jni: Add @CriticalNative optimization to speed up JNI transitions

Change-Id: I963059ac3a72dd8e6a867596c356d7062deb6da7
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index f9bc249..1392399 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -335,20 +335,30 @@
 }
 
 bool ArtMethod::IsAnnotatedWithFastNative() {
+  return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_FastNative,
+                         DexFile::kDexVisibilityBuild);
+}
+
+bool ArtMethod::IsAnnotatedWithCriticalNative() {
+  return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_CriticalNative,
+                         DexFile::kDexVisibilityBuild);
+}
+
+bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
   StackHandleScope<1> shs(self);
 
   const DexFile& dex_file = GetDeclaringClass()->GetDexFile();
 
-  mirror::Class* fast_native_annotation =
-      soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_annotation_optimization_FastNative);
-  Handle<mirror::Class> fast_native_handle(shs.NewHandle(fast_native_annotation));
+  mirror::Class* annotation = soa.Decode<mirror::Class*>(klass);
+  DCHECK(annotation->IsAnnotation());
+  Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation));
 
   // Note: Resolves any method annotations' classes as a side-effect.
   // -- This seems allowed by the spec since it says we can preload any classes
   //    referenced by another classes's constant pool table.
-  return dex_file.IsMethodAnnotationPresent(this, fast_native_handle, DexFile::kDexVisibilityBuild);
+  return dex_file.IsMethodAnnotationPresent(this, annotation_handle, visibility);
 }
 
 bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index b25087c..8051a1f 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -378,6 +378,10 @@
   // -- Independent of kAccFastNative access flags.
   bool IsAnnotatedWithFastNative();
 
+  // Checks to see if the method was annotated with @dalvik.annotation.optimization.CriticalNative
+  // -- Unrelated to the GC notion of "critical".
+  bool IsAnnotatedWithCriticalNative();
+
   // Returns true if this method could be overridden by a default method.
   bool IsOverridableByDefaultMethod() REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -776,6 +780,8 @@
   } ptr_sized_fields_;
 
  private:
+  bool IsAnnotatedWith(jclass klass, uint32_t visibility);
+
   static constexpr size_t PtrSizedFieldsOffset(PointerSize pointer_size) {
     // Round up to pointer size for padding field. Tested in art_method.cc.
     return RoundUp(offsetof(ArtMethod, hotness_count_) + sizeof(hotness_count_),
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 741b682..dba0a81 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -608,6 +608,10 @@
   EXPECT_TRUE(actual_.empty()) << actual_;
 }
 
+void CheckJniAbortCatcher::Check(const std::string& expected_text) {
+  Check(expected_text.c_str());
+}
+
 void CheckJniAbortCatcher::Check(const char* expected_text) {
   EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
       << "Expected to find: " << expected_text << "\n"
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 00394e9..b2090b7 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -184,6 +184,7 @@
 
   ~CheckJniAbortCatcher();
 
+  void Check(const std::string& expected_text);
   void Check(const char* expected_text);
 
  private:
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 2c99275..5f5fbc8 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -30,6 +30,7 @@
 namespace art {
 
 jclass WellKnownClasses::com_android_dex_Dex;
+jclass WellKnownClasses::dalvik_annotation_optimization_CriticalNative;
 jclass WellKnownClasses::dalvik_annotation_optimization_FastNative;
 jclass WellKnownClasses::dalvik_system_DexFile;
 jclass WellKnownClasses::dalvik_system_DexPathList;
@@ -216,6 +217,8 @@
 
 void WellKnownClasses::Init(JNIEnv* env) {
   com_android_dex_Dex = CacheClass(env, "com/android/dex/Dex");
+  dalvik_annotation_optimization_CriticalNative =
+      CacheClass(env, "dalvik/annotation/optimization/CriticalNative");
   dalvik_annotation_optimization_FastNative = CacheClass(env, "dalvik/annotation/optimization/FastNative");
   dalvik_system_DexFile = CacheClass(env, "dalvik/system/DexFile");
   dalvik_system_DexPathList = CacheClass(env, "dalvik/system/DexPathList");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 25c9424..ce710ff 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -41,6 +41,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   static jclass com_android_dex_Dex;
+  static jclass dalvik_annotation_optimization_CriticalNative;
   static jclass dalvik_annotation_optimization_FastNative;
   static jclass dalvik_system_DexFile;
   static jclass dalvik_system_DexPathList;