Fix -Xint mode.

Bug: 9700950

Make ClassLinker::FixupStaticTrampolines updates entry point from compiled code
with interpreter entry point when interpreter mode is enabled.

Change-Id: Ie52ace8ea054ae7cb17442264dc62f68472409c6
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 68d0fbb..159fbf7 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1560,6 +1560,18 @@
   return oat_class->GetOatMethod(oat_method_idx).GetCode();
 }
 
+// Returns true if the method must run with interpreter, false otherwise.
+static bool NeedsInterpreter(const mirror::AbstractMethod* method, const void* code) {
+  if (code == NULL) {
+    // No code: need interpreter.
+    return true;
+  }
+  // If interpreter mode is enabled, every method (except native and proxy) must
+  // be run with interpreter.
+  return Runtime::Current()->GetInstrumentation()->InterpretOnly() &&
+         !method->IsNative() && !method->IsProxyMethod();
+}
+
 void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
   ClassHelper kh(klass);
   const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
@@ -1584,19 +1596,20 @@
   while (it.HasNextInstanceField()) {
     it.Next();
   }
-  size_t method_index = 0;
   // Link the code of methods skipped by LinkCode
-  for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-    mirror::AbstractMethod* method = klass->GetDirectMethod(i);
-    if (method->IsStatic()) {
-      const void* code = oat_class->GetOatMethod(method_index).GetCode();
-      if (code == NULL) {
-        // No code? You must mean to go into the interpreter.
-        code = GetInterpreterEntryPoint();
-      }
-      runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
+  for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
+    mirror::AbstractMethod* method = klass->GetDirectMethod(method_index);
+    if (!method->IsStatic()) {
+      // Only update static methods.
+      continue;
     }
-    method_index++;
+    const void* code = oat_class->GetOatMethod(method_index).GetCode();
+    const bool enter_interpreter = NeedsInterpreter(method, code);
+    if (enter_interpreter) {
+      // Use interpreter entry point.
+      code = GetInterpreterEntryPoint();
+    }
+    runtime->GetInstrumentation()->UpdateMethodsCode(method, code);
   }
   // Ignore virtual methods on the iterator.
 }
@@ -1613,9 +1626,7 @@
 
   // Install entry point from interpreter.
   Runtime* runtime = Runtime::Current();
-  bool enter_interpreter = method->GetEntryPointFromCompiledCode() == NULL ||
-                           (runtime->GetInstrumentation()->InterpretOnly() &&
-                           !method->IsNative() && !method->IsProxyMethod());
+  bool enter_interpreter = NeedsInterpreter(method.get(), method->GetEntryPointFromCompiledCode());
   if (enter_interpreter) {
     method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterEntry);
   } else {
@@ -1629,7 +1640,12 @@
 
   if (method->IsStatic() && !method->IsConstructor()) {
     // For static methods excluding the class initializer, install the trampoline.
+    // It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
+    // after initializing class (see ClassLinker::InitializeClass method).
     method->SetEntryPointFromCompiledCode(GetResolutionTrampoline(runtime->GetClassLinker()));
+  } else if (enter_interpreter) {
+    // Set entry point from compiled code if there's no code or in interpreter only mode.
+    method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
   }
 
   if (method->IsNative()) {
@@ -1637,11 +1653,6 @@
     method->UnregisterNative(Thread::Current());
   }
 
-  if (enter_interpreter) {
-    // Set entry point from compiled code if there's no code or in interpreter only mode.
-    method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
-  }
-
   // Allow instrumentation its chance to hijack code.
   runtime->GetInstrumentation()->UpdateMethodsCode(method.get(),
                                                    method->GetEntryPointFromCompiledCode());
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 5ea1f77..cbdf3cd 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -135,21 +135,7 @@
   if (UNLIKELY(soa.Env()->check_jni)) {
     CheckMethodArguments(method, args);
   }
-  // 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);
-  }
+  method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, result_type);
 }
 
 static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,