Interpret methods invoked via JNI in interpreter only mode.

This fixes the issue of Dhrystone having the same performance in
interpreter only mode. Main was executing compiled code since it
uses CallStaticVoidMethod directly. Now a check for interpreter
only mode in InvokeWithArgArray redirects it to the interpreter.

Change-Id: If6e6d8ede5cd0d8ad687d161667056373b1b031c
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 21725de..a89fb11 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -348,6 +348,13 @@
         jresult = fn(soa.Env(), rcvr.get());
       }
       result->SetL(soa.Decode<Object*>(jresult));
+    } else if (shorty == "V") {
+      typedef void (fnptr)(JNIEnv*, jobject);
+      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
+      ScopedLocalRef<jobject> rcvr(soa.Env(),
+                                   soa.AddLocalReference<jobject>(receiver));
+      ScopedThreadStateChange tsc(self, kNative);
+      fn(soa.Env(), rcvr.get());
     } else if (shorty == "LL") {
       typedef jobject (fnptr)(JNIEnv*, jobject, jobject);
       const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 50b28b8..5ea1f77 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -29,6 +29,7 @@
 #include "class_linker.h"
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
+#include "interpreter/interpreter.h"
 #include "invoke_arg_array_builder.h"
 #include "jni.h"
 #include "mirror/class-inl.h"
@@ -130,10 +131,25 @@
 void InvokeWithArgArray(const ScopedObjectAccess& soa, AbstractMethod* method,
                         ArgArray* arg_array, JValue* result, char result_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t* args = arg_array->GetArray();
   if (UNLIKELY(soa.Env()->check_jni)) {
-    CheckMethodArguments(method, arg_array->GetArray());
+    CheckMethodArguments(method, args);
   }
-  method->Invoke(soa.Self(), arg_array->GetArray(), arg_array->GetNumBytes(), result, result_type);
+  // Check interpreter only mode for methods invoked through JNI.
+  // TODO: Check that this catches all remaining paths to invoke.
+  // TODO: Move check up a level to avoid building arg array and then shadow frame?
+  if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
+    Object* receiver = method->IsStatic() ? NULL : reinterpret_cast<Object*>(args[0]);
+    if (!method->IsStatic()) {
+      args++;
+    }
+    ManagedStack fragment;
+    soa.Self()->PushManagedStackFragment(&fragment);
+    art::interpreter::EnterInterpreterFromInvoke(soa.Self(), method, receiver, args, result);
+    soa.Self()->PopManagedStackFragment(fragment);
+  } else {
+    method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, result_type);
+  }
 }
 
 static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,