Fast JNI support.

Use a modifier to signal a native method is a fast JNI method. If the
modifier is set then don't perform runnable transitions.

Change-Id: I7835b4d837bfdd1cb8e2d54b919c0d5e6cf90499
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index cd05f41..f5c0e9f 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -306,11 +306,15 @@
 }
 
 extern "C" void art_work_around_app_jni_bugs(JNIEnv*, jobject);
-void ArtMethod::RegisterNative(Thread* self, const void* native_method) {
+void ArtMethod::RegisterNative(Thread* self, const void* native_method, bool is_fast) {
   DCHECK(Thread::Current() == self);
   CHECK(IsNative()) << PrettyMethod(this);
+  CHECK(!IsFastNative()) << PrettyMethod(this);
   CHECK(native_method != NULL) << PrettyMethod(this);
   if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) {
+    if (is_fast) {
+      SetAccessFlags(GetAccessFlags() | kAccFastNative);
+    }
     SetNativeMethod(native_method);
   } else {
     // We've been asked to associate this method with the given native method but are working
@@ -328,9 +332,9 @@
 }
 
 void ArtMethod::UnregisterNative(Thread* self) {
-  CHECK(IsNative()) << PrettyMethod(this);
+  CHECK(IsNative() && !IsFastNative()) << PrettyMethod(this);
   // restore stub to lookup native pointer via dlsym
-  RegisterNative(self, GetJniDlsymLookupStub());
+  RegisterNative(self, GetJniDlsymLookupStub(), false);
 }
 
 void ArtMethod::SetNativeMethod(const void* native_method) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 5d4a6ea..0520893 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -112,6 +112,10 @@
     return (GetAccessFlags() & kAccNative) != 0;
   }
 
+  bool IsFastNative() const {
+    return (GetAccessFlags() & kAccFastNative) != 0;
+  }
+
   bool IsAbstract() const {
     return (GetAccessFlags() & kAccAbstract) != 0;
   }
@@ -307,7 +311,7 @@
 
   bool IsRegistered() const;
 
-  void RegisterNative(Thread* self, const void* native_method)
+  void RegisterNative(Thread* self, const void* native_method, bool is_fast)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 2b0b1e1..319ca4a 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -661,7 +661,9 @@
     for (int32_t index = 0, end = methods->GetLength(); index < end; ++index) {
       mirror::ArtMethod* method = methods->GetWithoutChecks(index);
       DCHECK(method != NULL);
-      method->SetPreverified();
+      if (!method->IsNative() && !method->IsAbstract()) {
+        method->SetPreverified();
+      }
     }
   }
 }