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 <stdio.h>
18#include <jni.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
38static void NativeMethods_emptyJniStaticSynchronizedMethod0(JNIEnv*, jclass) { }
39static void NativeMethods_emptyJniSynchronizedMethod0(JNIEnv*, jclass) { }
40
41static JNINativeMethod gMethods_NormalOnly[] = {
42  NATIVE_METHOD(NativeMethods, emptyJniStaticSynchronizedMethod0, "()V"),
43  NATIVE_METHOD(NativeMethods, emptyJniSynchronizedMethod0, "()V"),
44};
45
46static void NativeMethods_emptyJniMethod0(JNIEnv*, jobject) { }
47static void NativeMethods_emptyJniMethod6(JNIEnv*, jobject, int, int, int, int, int, int) { }
48static void NativeMethods_emptyJniMethod6L(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
49                                           jarray, jarray) { }
50static void NativeMethods_emptyJniStaticMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject,
51                                                 jarray, jarray) { }
52
53static void NativeMethods_emptyJniStaticMethod0(JNIEnv*, jclass) { }
54static void NativeMethods_emptyJniStaticMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
55
56static 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
65static void NativeMethods_emptyJniMethod0_Fast(JNIEnv*, jobject) { }
66static void NativeMethods_emptyJniMethod6_Fast(JNIEnv*, jobject, int, int, int, int, int, int) { }
67static void NativeMethods_emptyJniMethod6L_Fast(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
68                                                jarray, jarray) { }
69static void NativeMethods_emptyJniStaticMethod6L_Fast(JNIEnv*, jclass, jobject, jarray, jarray,
70                                                      jobject, jarray, jarray) { }
71
72static void NativeMethods_emptyJniStaticMethod0_Fast(JNIEnv*, jclass) { }
73static void NativeMethods_emptyJniStaticMethod6_Fast(JNIEnv*, jclass, int, int, int, int, int, int) { }
74
75static 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.
86DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod0_1Critical)(JNIEnv*, jclass) { }
87DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod0_1Critical)() { }
88DEFINE_NORMAL_JNI_METHOD(void,   emptyJniStaticMethod6_1Critical)(JNIEnv*, jclass, int, int, int, int, int, int) { }
89DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod6_1Critical)(int, int, int, int, int, int) { }
90
91static 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
99void 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
131void 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