/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <stdio.h>
#ifndef NATIVE_METHOD
#define NATIVE_METHOD(className, functionName, signature) \
{ #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
#endif
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#define GLUE4(a, b, c, d) a ## b ## c ## d
#define GLUE4_(a, b, c, d) GLUE4(a, b, c, d)
#define CLASS_NAME "benchmarks/MicroNative/java/NativeMethods"
#define CLASS_INFIX benchmarks_MicroNative_java_NativeMethods
#define NAME_NORMAL_JNI_METHOD(name) GLUE4_(Java_, CLASS_INFIX, _, name)
#define NAME_CRITICAL_JNI_METHOD(name) GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
#define DEFINE_NORMAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(Java_, CLASS_INFIX, _, name)
#define DEFINE_CRITICAL_JNI_METHOD(ret, name) extern "C" JNIEXPORT ret JNICALL GLUE4_(JavaCritical_, CLASS_INFIX, _, name)
static void NativeMethods_emptyJniStaticSynchronizedMethod0(JNIEnv*, jclass) { }
static void NativeMethods_emptyJniSynchronizedMethod0(JNIEnv*, jclass) { }
static JNINativeMethod gMethods_NormalOnly[] = {
NATIVE_METHOD(NativeMethods, emptyJniStaticSynchronizedMethod0, "()V"),
NATIVE_METHOD(NativeMethods, emptyJniSynchronizedMethod0, "()V"),
};
static void NativeMethods_emptyJniMethod0(JNIEnv*, jobject) { }
static void NativeMethods_emptyJniMethod6(JNIEnv*, jobject, int, int, int, int, int, int) { }
static void NativeMethods_emptyJniMethod6L(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
jarray, jarray) { }
static void NativeMethods_emptyJniStaticMethod6L(JNIEnv*, jclass, jobject, jarray, jarray, jobject,
jarray, jarray) { }
static void NativeMethods_emptyJniStaticMethod0(JNIEnv*, jclass) { }
static void NativeMethods_emptyJniStaticMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(NativeMethods, emptyJniMethod0, "()V"),
NATIVE_METHOD(NativeMethods, emptyJniMethod6, "(IIIIII)V"),
NATIVE_METHOD(NativeMethods, emptyJniMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6L, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod0, "()V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6, "(IIIIII)V"),
};
static void NativeMethods_emptyJniMethod0_Fast(JNIEnv*, jobject) { }
static void NativeMethods_emptyJniMethod6_Fast(JNIEnv*, jobject, int, int, int, int, int, int) { }
static void NativeMethods_emptyJniMethod6L_Fast(JNIEnv*, jobject, jobject, jarray, jarray, jobject,
jarray, jarray) { }
static void NativeMethods_emptyJniStaticMethod6L_Fast(JNIEnv*, jclass, jobject, jarray, jarray,
jobject, jarray, jarray) { }
static void NativeMethods_emptyJniStaticMethod0_Fast(JNIEnv*, jclass) { }
static void NativeMethods_emptyJniStaticMethod6_Fast(JNIEnv*, jclass, int, int, int, int, int, int) { }
static JNINativeMethod gMethods_Fast[] = {
NATIVE_METHOD(NativeMethods, emptyJniMethod0_Fast, "()V"),
NATIVE_METHOD(NativeMethods, emptyJniMethod6_Fast, "(IIIIII)V"),
NATIVE_METHOD(NativeMethods, emptyJniMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6L_Fast, "(Ljava/lang/String;[Ljava/lang/String;[[ILjava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod0_Fast, "()V"),
NATIVE_METHOD(NativeMethods, emptyJniStaticMethod6_Fast, "(IIIIII)V"),
};
// Have both a Java_ and a JavaCritical_ version of the same empty method.
// The runtime automatically selects the right one when doing a dlsym-based native lookup.
DEFINE_NORMAL_JNI_METHOD(void, emptyJniStaticMethod0_1Critical)(JNIEnv*, jclass) { }
DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod0_1Critical)() { }
DEFINE_NORMAL_JNI_METHOD(void, emptyJniStaticMethod6_1Critical)(JNIEnv*, jclass, int, int, int, int, int, int) { }
DEFINE_CRITICAL_JNI_METHOD(void, emptyJniStaticMethod6_1Critical)(int, int, int, int, int, int) { }
static JNINativeMethod gMethods_Critical[] = {
// Don't use NATIVE_METHOD because the name is mangled differently.
{ "emptyJniStaticMethod0_Critical", "()V",
reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod0_1Critical)) },
{ "emptyJniStaticMethod6_Critical", "(IIIIII)V",
reinterpret_cast<void*>(NAME_CRITICAL_JNI_METHOD(emptyJniStaticMethod6_1Critical)) }
};
void jniRegisterNativeMethods(JNIEnv* env,
const char* className,
const JNINativeMethod* methods,
int numMethods) {
jclass c = env->FindClass(className);
if (c == nullptr) {
char* tmp;
const char* msg;
if (asprintf(&tmp,
"Native registration unable to find class '%s'; aborting...",
className) == -1) {
// Allocation failed, print default warning.
msg = "Native registration unable to find class; aborting...";
} else {
msg = tmp;
}
env->FatalError(msg);
}
if (env->RegisterNatives(c, methods, numMethods) < 0) {
char* tmp;
const char* msg;
if (asprintf(&tmp, "RegisterNatives failed for '%s'; aborting...", className) == -1) {
// Allocation failed, print default warning.
msg = "RegisterNatives failed; aborting...";
} else {
msg = tmp;
}
env->FatalError(msg);
}
}
void register_micro_native_methods(JNIEnv* env) {
jniRegisterNativeMethods(env, CLASS_NAME, gMethods_NormalOnly, NELEM(gMethods_NormalOnly));
jniRegisterNativeMethods(env, CLASS_NAME, gMethods, NELEM(gMethods));
jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Fast, NELEM(gMethods_Fast));
if (env->FindClass("dalvik/annotation/optimization/CriticalNative") != nullptr) {
// Only register them explicitly if the annotation is present.
jniRegisterNativeMethods(env, CLASS_NAME, gMethods_Critical, NELEM(gMethods_Critical));
} else {
if (env->ExceptionCheck()) {
// It will throw NoClassDefFoundError
env->ExceptionClear();
}
}
// else let them be registered implicitly.
}