1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <jni.h>
18 #include <stdio.h>
19 
20 #ifndef NATIVE_METHOD
21 #define NATIVE_METHOD(className, functionName, signature) \
22     { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
23 #endif
24 #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
25 
26 #define GLUE4(a, b, c, d) a ## b ## c ## d
27 #define GLUE4_(a, b, c, d) GLUE4(a, b, c, d)
28 
29 #define CLASS_NAME "benchmarks/MicroNative/java/NativeMethods"
30 #define CLASS_INFIX benchmarks_MicroNative_java_NativeMethods
31 
32 #define NAME_NORMAL_JNI_METHOD(name) GLUE4_(Java_, CLASS_INFIX, _, name)
33 #define NAME_CRITICAL_JNI_METHOD(name) GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
34 
35 #define DEFINE_NORMAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(Java_, CLASS_INFIX, _, name)
36 #define DEFINE_CRITICAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
37 
NativeMethods_emptyJniStaticSynchronizedMethod0(JNIEnv *,jclass)38 static void NativeMethods_emptyJniStaticSynchronizedMethod0(JNIEnv*, jclass) { }
NativeMethods_emptyJniSynchronizedMethod0(JNIEnv *,jclass)39 static void NativeMethods_emptyJniSynchronizedMethod0(JNIEnv*, jclass) { }
40 
41 static JNINativeMethod gMethods_NormalOnly[] = {
42   NATIVE_METHOD(NativeMethods, emptyJniStaticSynchronizedMethod0, "()V"),
43   NATIVE_METHOD(NativeMethods, emptyJniSynchronizedMethod0, "()V"),
44 };
45 
NativeMethods_emptyJniMethod0(JNIEnv *,jobject)46 static void NativeMethods_emptyJniMethod0(JNIEnv*, jobject) { }
NativeMethods_emptyJniMethod6(JNIEnv *,jobject,int,int,int,int,int,int)47 static void NativeMethods_emptyJniMethod6(JNIEnv*, jobject, int, int, int, int, int, int) { }
NativeMethods_emptyJniMethod6L(JNIEnv *,jobject,jobject,jarray,jarray,jobject,jarray,jarray)48 static void NativeMethods_emptyJniMethod6L(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
49                                            jarray, jarray) { }
NativeMethods_emptyJniStaticMethod6L(JNIEnv *,jclass,jobject,jarray,jarray,jobject,jarray,jarray)50 static void NativeMethods_emptyJniStaticMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject,
51                                                  jarray, jarray) { }
52 
NativeMethods_emptyJniStaticMethod0(JNIEnv *,jclass)53 static void NativeMethods_emptyJniStaticMethod0(JNIEnv*, jclass) { }
NativeMethods_emptyJniStaticMethod6(JNIEnv *,jclass,int,int,int,int,int,int)54 static void NativeMethods_emptyJniStaticMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
55 
56 static JNINativeMethod gMethods[] = {
57   NATIVE_METHOD(NativeMethods, emptyJniMethod0, "()V"),
58   NATIVE_METHOD(NativeMethods, emptyJniMethod6, "(IIIIII)V"),
59   NATIVE_METHOD(NativeMethods, emptyJniMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
60   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
61   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod0, "()V"),
62   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6, "(IIIIII)V"),
63 };
64 
NativeMethods_emptyJniMethod0_Fast(JNIEnv *,jobject)65 static void NativeMethods_emptyJniMethod0_Fast(JNIEnv*, jobject) { }
NativeMethods_emptyJniMethod6_Fast(JNIEnv *,jobject,int,int,int,int,int,int)66 static void NativeMethods_emptyJniMethod6_Fast(JNIEnv*, jobject, int, int, int, int, int, int) { }
NativeMethods_emptyJniMethod6L_Fast(JNIEnv *,jobject,jobject,jarray,jarray,jobject,jarray,jarray)67 static void NativeMethods_emptyJniMethod6L_Fast(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
68                                                 jarray, jarray) { }
NativeMethods_emptyJniStaticMethod6L_Fast(JNIEnv *,jclass,jobject,jarray,jarray,jobject,jarray,jarray)69 static void NativeMethods_emptyJniStaticMethod6L_Fast(JNIEnv*, jclass, jobject, jarray, jarray,
70                                                       jobject, jarray, jarray) { }
71 
NativeMethods_emptyJniStaticMethod0_Fast(JNIEnv *,jclass)72 static void NativeMethods_emptyJniStaticMethod0_Fast(JNIEnv*, jclass) { }
NativeMethods_emptyJniStaticMethod6_Fast(JNIEnv *,jclass,int,int,int,int,int,int)73 static void NativeMethods_emptyJniStaticMethod6_Fast(JNIEnv*, jclass, int, int, int, int, int, int) { }
74 
75 static JNINativeMethod gMethods_Fast[] = {
76   NATIVE_METHOD(NativeMethods, emptyJniMethod0_Fast, "()V"),
77   NATIVE_METHOD(NativeMethods, emptyJniMethod6_Fast, "(IIIIII)V"),
78   NATIVE_METHOD(NativeMethods, emptyJniMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
79   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
80   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod0_Fast, "()V"),
81   NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6_Fast, "(IIIIII)V"),
82 };
83 
84 // Have both a Java_ and a JavaCritical_ version of the same empty method.
85 // The runtime automatically selects the right one when doing a dlsym-based native lookup.
DEFINE_NORMAL_JNI_METHOD(void,emptyJniStaticMethod0_1Critical)86 DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod0_1Critical)(JNIEnv*, jclass) { }
DEFINE_CRITICAL_JNI_METHOD(void,emptyJniStaticMethod0_1Critical)87 DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod0_1Critical)() { }
DEFINE_NORMAL_JNI_METHOD(void,emptyJniStaticMethod6_1Critical)88 DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod6_1Critical)(JNIEnv*, jclass, int, int, int, int, int, int) { }
DEFINE_CRITICAL_JNI_METHOD(void,emptyJniStaticMethod6_1Critical)89 DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod6_1Critical)(int, int, int, int, int, int) { }
90 
91 static JNINativeMethod gMethods_Critical[] = {
92   // Don't use NATIVE_METHOD because the name is mangled differently.
93   { "emptyJniStaticMethod0_Critical", "()V",
94         reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod0_1Critical)) },
95   { "emptyJniStaticMethod6_Critical", "(IIIIII)V",
96         reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod6_1Critical)) }
97 };
98 
jniRegisterNativeMethods(JNIEnv * env,const char * className,const JNINativeMethod * methods,int numMethods)99 void jniRegisterNativeMethods(JNIEnv* env,
100                               const char* className,
101                               const JNINativeMethod* methods,
102                               int numMethods) {
103     jclass c = env->FindClass(className);
104     if (c == nullptr) {
105         char* tmp;
106         const char* msg;
107         if (asprintf(&tmp,
108                      "Native registration unable to find class '%s'; aborting...",
109                      className) == -1) {
110             // Allocation failed, print default warning.
111             msg = "Native registration unable to find class; aborting...";
112         } else {
113             msg = tmp;
114         }
115         env->FatalError(msg);
116     }
117 
118     if (env->RegisterNatives(c, methods, numMethods) < 0) {
119         char* tmp;
120         const char* msg;
121         if (asprintf(&tmp, "RegisterNatives failed for '%s'; aborting...", className) == -1) {
122             // Allocation failed, print default warning.
123             msg = "RegisterNatives failed; aborting...";
124         } else {
125             msg = tmp;
126         }
127         env->FatalError(msg);
128     }
129 }
130 
register_micro_native_methods(JNIEnv * env)131 void register_micro_native_methods(JNIEnv* env) {
132   jniRegisterNativeMethods(env, CLASS_NAME, gMethods_NormalOnly, NELEM(gMethods_NormalOnly));
133   jniRegisterNativeMethods(env, CLASS_NAME, gMethods, NELEM(gMethods));
134   jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Fast, NELEM(gMethods_Fast));
135 
136   if (env->FindClass("dalvik/annotation/optimization/CriticalNative") != nullptr) {
137     // Only register them explicitly if the annotation is present.
138     jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Critical, NELEM(gMethods_Critical));
139   } else {
140     if (env->ExceptionCheck()) {
141       // It will throw NoClassDefFoundError
142       env->ExceptionClear();
143     }
144   }
145   // else let them be registered implicitly.
146 }
147