Switch -Xjnitrace over to using a custom JNI bridge.

This now works without needing to specify -Xint:portable, and no longer needs
to be manually enabled at compile-time.

If you're using -Xjnitrace, you'll pay to look up the real JNI bridge on every
invocation of a native method, but doing so leads to a really simple
implementation, and you're writing to the log on every invocation anyway, so
-Xjnitrace and performance don't go together anyway.

Bug: 2846017

Change-Id: I3108c4f35f27b72e8849c41077ae3e8768550e96
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index ba580d0..8626375 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -32,7 +32,6 @@
 # Optional features.  These may impact the size or performance of the VM.
 #
 LOCAL_CFLAGS += -DWITH_PROFILER -DWITH_DEBUGGER
-#LOCAL_CFLAGS += -DWITH_JNI_TRACE
 
 # 0=full cache, 1/2=reduced, 3=no cache
 LOCAL_CFLAGS += -DDVM_RESOLVER_CACHE=0
diff --git a/vm/Init.c b/vm/Init.c
index d73bec7..06ceabc 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -111,9 +111,7 @@
     dvmFprintf(stderr,
                 "  -Xjnigreflimit:N  (must be multiple of 100, >= 200)\n");
     dvmFprintf(stderr, "  -Xjniopts:{warnonly,forcecopy}\n");
-#if defined(WITH_JNI_TRACE)
     dvmFprintf(stderr, "  -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
-#endif
     dvmFprintf(stderr, "  -Xdeadlockpredict:{off,warn,err,abort}\n");
     dvmFprintf(stderr, "  -Xstacktracefile:<filename>\n");
     dvmFprintf(stderr, "  -Xgc:[no]precise\n");
@@ -179,9 +177,6 @@
 #ifdef WITH_JNI_STACK_CHECK
         " jni_stack_check"
 #endif
-#ifdef WITH_JNI_TRACE
-        " jni_trace"
-#endif
 #ifdef EASY_GDB
         " easy_gdb"
 #endif
@@ -891,12 +886,8 @@
                 return -1;
             }
             gDvm.jniGrefLimit = lim;
-
-#if defined(WITH_JNI_TRACE)
         } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
             gDvm.jniTrace = strdup(argv[i] + 11);
-#endif
-
         } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
             gDvm.logStdio = true;
 
diff --git a/vm/Jni.c b/vm/Jni.c
index 77aeb69..8967f46 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -1333,10 +1333,10 @@
 }
 
 /*
- * Point "method->nativeFunc" at the JNI bridge, and overload "method->insns"
- * to point at the actual function.
+ * Returns the appropriate JNI bridge for 'method', also taking into account
+ * the -Xcheck:jni setting.
  */
-void dvmUseJNIBridge(Method* method, void* func)
+static DalvikBridgeFunc dvmSelectJNIBridge(const Method* method)
 {
     enum {
         kJNIGeneral = 0,
@@ -1388,11 +1388,39 @@
         }
     }
 
-    if (dvmIsCheckJNIEnabled()) {
-        dvmSetNativeFunc(method, checkFunc[kind], func);
-    } else {
-        dvmSetNativeFunc(method, stdFunc[kind], func);
-    }
+    return dvmIsCheckJNIEnabled() ? checkFunc[kind] : stdFunc[kind];
+}
+
+/*
+ * Trace a call into native code.
+ */
+static void dvmTraceCallJNIMethod(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmLogNativeMethodEntry(method, args);
+    DalvikBridgeFunc bridge = dvmSelectJNIBridge(method);
+    (*bridge)(args, pResult, method, self);
+    dvmLogNativeMethodExit(method, self, *pResult);
+}
+
+/**
+ * Returns true if the -Xjnitrace setting implies we should trace 'method'.
+ */
+static bool shouldTrace(Method* method)
+{
+    return gDvm.jniTrace && strstr(method->clazz->descriptor, gDvm.jniTrace);
+}
+
+/*
+ * Point "method->nativeFunc" at the JNI bridge, and overload "method->insns"
+ * to point at the actual function.
+ */
+void dvmUseJNIBridge(Method* method, void* func)
+{
+    DalvikBridgeFunc bridge = shouldTrace(method)
+        ? dvmTraceCallJNIMethod
+        : dvmSelectJNIBridge(method);
+    dvmSetNativeFunc(method, bridge, func);
 }
 
 /*
diff --git a/vm/Native.c b/vm/Native.c
index a641c25..4793ab3 100644
--- a/vm/Native.c
+++ b/vm/Native.c
@@ -943,10 +943,10 @@
 
 #define LOGI_NATIVE(...) LOG(LOG_INFO, LOG_TAG "-native", __VA_ARGS__)
 
-void dvmLogNativeMethodEntry(const Method* method, u4* fp)
+void dvmLogNativeMethodEntry(const Method* method, const u4* args)
 {
     char thisString[32] = { 0 };
-    u4* sp = &fp[method->registersSize - method->insSize];
+    const u4* sp = args; // &args[method->registersSize - method->insSize];
     if (!dvmIsStaticMethod(method)) {
         sprintf(thisString, "this=0x%08x ", *sp++);
     }
diff --git a/vm/Native.h b/vm/Native.h
index 5739647..a5e9ca1 100644
--- a/vm/Native.h
+++ b/vm/Native.h
@@ -114,7 +114,7 @@
  * Used to implement -Xjnitrace.
  */
 struct Thread;
-void dvmLogNativeMethodEntry(const Method* method, u4* newFp);
+void dvmLogNativeMethodEntry(const Method* method, const u4* newFp);
 void dvmLogNativeMethodExit(const Method* method, struct Thread* self,
         const JValue retval);
 
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index 589f974..842171d 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -917,14 +917,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -956,12 +948,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 8f7f4ec..4a7a5a9 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -4051,14 +4051,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -4090,12 +4082,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 92b97b0..44916fb 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -4335,14 +4335,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -4374,12 +4366,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index 9be8a8e..e863abe 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -4074,14 +4074,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -4113,12 +4105,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
index 13d05cc..46e25b0 100644
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ b/vm/mterp/out/InterpC-x86-atom.c
@@ -2245,14 +2245,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -2284,12 +2276,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 1ce0302..6fc1ce1 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -2182,14 +2182,6 @@
             TRACE_METHOD_ENTER(self, methodToCall);
 #endif
 
-#if defined(WITH_JNI_TRACE)
-            bool trace = gDvm.jniTrace &&
-                    strstr(methodToCall->clazz->descriptor, gDvm.jniTrace);
-            if (trace) {
-                dvmLogNativeMethodEntry(methodToCall, newFp);
-            }
-            else
-#endif
             {
                 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                         methodToCall->name, methodToCall->shorty);
@@ -2221,12 +2213,6 @@
             dvmPopJniLocals(self, newSaveArea);
             self->curFrame = fp;
 
-#if defined(WITH_JNI_TRACE)
-            if (trace) {
-                dvmLogNativeMethodExit(methodToCall, self, retval);
-            }
-#endif
-
             /*
              * If the native code threw an exception, or interpreted code
              * invoked by the native call threw one and nobody has cleared