diff --git a/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp b/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp index 5395536be..10556ed42 100644 --- a/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp +++ b/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp @@ -7,9 +7,75 @@ using namespace std; using namespace tns; +Runtime* TryGetRuntime(int runtimeId); + +namespace { +jint GenerateNewObjectIdFast(jint runtimeId) { + auto runtime = TryGetRuntime(runtimeId); + if (runtime == nullptr) { + return 0; + } + + return runtime->GenerateNewObjectId(nullptr, nullptr); +} + +jboolean NotifyGcFast(JNIEnv* env, jclass, jobject runtimeObject, jint runtimeId) { + auto runtime = TryGetRuntime(runtimeId); + if (runtime == nullptr) { + return JNI_FALSE; + } + + return runtime->NotifyGC(env, runtimeObject) ? JNI_TRUE : JNI_FALSE; +} + +jint GetPointerSizeFast() { + return sizeof(void*); +} + +jint GetCurrentRuntimeIdFast() { + Isolate* isolate = Isolate::TryGetCurrent(); + if (isolate == nullptr) { + return -1; + } + + Runtime* runtime = Runtime::GetRuntime(isolate); + return runtime->GetId(); +} + +void SetManualInstrumentationModeFast(JNIEnv*, jclass, jstring mode) { + Runtime::SetManualInstrumentationMode(mode); +} + +void RegisterRuntimeNativeFastMethods(JNIEnv* env) { + jclass runtimeNativeFastClass = env->FindClass("com/tns/RuntimeNativeFast"); + if (runtimeNativeFastClass == nullptr) { + throw NativeScriptException("Unable to find com/tns/RuntimeNativeFast for JNI registration."); + } + + JNINativeMethod methods[] = { + { const_cast("generateNewObjectId"), const_cast("(I)I"), reinterpret_cast(GenerateNewObjectIdFast) }, + { const_cast("notifyGc"), const_cast("(Lcom/tns/Runtime;I)Z"), reinterpret_cast(NotifyGcFast) }, + { const_cast("getCurrentRuntimeId"), const_cast("()I"), reinterpret_cast(GetCurrentRuntimeIdFast) }, + { const_cast("getPointerSize"), const_cast("()I"), reinterpret_cast(GetPointerSizeFast) }, + { const_cast("SetManualInstrumentationMode"), const_cast("(Ljava/lang/String;)V"), reinterpret_cast(SetManualInstrumentationModeFast) }, + }; + + if (env->RegisterNatives(runtimeNativeFastClass, methods, sizeof(methods) / sizeof(methods[0])) != JNI_OK) { + throw NativeScriptException("Unable to register com/tns/RuntimeNativeFast native methods."); + } + + env->DeleteLocalRef(runtimeNativeFastClass); +} +} // namespace + JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { try { Runtime::Init(vm, reserved); + JNIEnv* env = nullptr; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK || env == nullptr) { + throw NativeScriptException("Unable to retrieve JNIEnv during JNI_OnLoad."); + } + RegisterRuntimeNativeFastMethods(env); } catch (NativeScriptException& e) { e.ReThrowToJava(); } catch (std::exception e) { @@ -25,8 +91,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { return JNI_VERSION_1_6; } -// @FastNative signature - optimized JNI, keeps JNIEnv* for jstring handling -extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationMode(JNIEnv* _env, jobject obj, jstring mode) { +extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationModeLegacy(JNIEnv*, jclass, jstring mode) { try { Runtime::SetManualInstrumentationMode(mode); } catch (...) { @@ -215,14 +280,9 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_createJSInstanceNative(JNIEnv* _e } } -// @CriticalNative signature - no JNIEnv* or jobject parameters -extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(jint runtimeId) { +extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectIdLegacy(JNIEnv*, jclass, jint runtimeId) { try { - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - return 0; - } - return runtime->GenerateNewObjectId(nullptr, nullptr); + return GenerateNewObjectIdFast(runtimeId); } catch (NativeScriptException& e) { e.ReThrowToJava(); } catch (std::exception e) { @@ -238,15 +298,8 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(jint runtimeI return 0; } -// @FastNative signature - optimized JNI, keeps JNIEnv* for NotifyGC -extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* env, jobject obj, jint runtimeId) { - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - return JNI_FALSE; - } - - jboolean success = runtime->NotifyGC(env, obj) ? JNI_TRUE : JNI_FALSE; - return success; +extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGcLegacy(JNIEnv* env, jobject obj, jint runtimeId) { + return NotifyGcFast(env, nullptr, obj, runtimeId); } extern "C" JNIEXPORT void Java_com_tns_Runtime_lock(JNIEnv* env, jobject obj, jint runtimeId) { @@ -291,21 +344,12 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* e } } -// @CriticalNative signature - no JNIEnv* or jobject parameters -extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSize() { - return sizeof(void*); +extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSizeLegacy(JNIEnv*, jclass) { + return GetPointerSizeFast(); } -// @CriticalNative signature - no JNIEnv* or jobject parameters -extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeId() { - Isolate* isolate = Isolate::TryGetCurrent(); - if (isolate == nullptr) { - return -1; - } - - Runtime* runtime = Runtime::GetRuntime(isolate); - int id = runtime->GetId(); - return id; +extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeIdLegacy(JNIEnv*, jclass) { + return GetCurrentRuntimeIdFast(); } extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerGlobalOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jstring msg) { @@ -415,4 +459,4 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(J auto isolate = runtime->GetIsolate(); isolate->DateTimeConfigurationChangeNotification(Isolate::TimeZoneDetection::kRedetect); -} \ No newline at end of file +} diff --git a/test-app/runtime/src/main/java/com/tns/Runtime.java b/test-app/runtime/src/main/java/com/tns/Runtime.java index 0e565526d..0887edaf9 100644 --- a/test-app/runtime/src/main/java/com/tns/Runtime.java +++ b/test-app/runtime/src/main/java/com/tns/Runtime.java @@ -1,5 +1,6 @@ package com.tns; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -31,15 +32,15 @@ import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Collections; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.RunnableFuture; import java.util.concurrent.atomic.AtomicInteger; -import java.util.Collections; -import dalvik.annotation.optimization.CriticalNative; -import dalvik.annotation.optimization.FastNative; public class Runtime { + private static final boolean USE_FAST_NATIVE_METHODS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; + private native void initNativeScript(int runtimeId, String filesPath, String nativeLibDir, boolean verboseLoggingEnabled, boolean isDebuggable, String packageName, Object[] v8Options, String callingDir, int maxLogcatObjectSize, boolean forceLog); @@ -53,11 +54,25 @@ private native void initNativeScript(int runtimeId, String filesPath, String nat private native void createJSInstanceNative(int runtimeId, Object javaObject, int javaObjectID, String canonicalName); - @CriticalNative - private static native int generateNewObjectId(int runtimeId); + private static int generateNewObjectId(int runtimeId) { + if (USE_FAST_NATIVE_METHODS) { + return RuntimeNativeFast.generateNewObjectId(runtimeId); + } + + return generateNewObjectIdLegacy(runtimeId); + } + + private static native int generateNewObjectIdLegacy(int runtimeId); + + private boolean notifyGc(int runtimeId) { + if (USE_FAST_NATIVE_METHODS) { + return RuntimeNativeFast.notifyGc(this, runtimeId); + } + + return notifyGcLegacy(runtimeId); + } - @FastNative - private native boolean notifyGc(int runtimeId); + private native boolean notifyGcLegacy(int runtimeId); private native void lock(int runtimeId); @@ -65,14 +80,36 @@ private native void initNativeScript(int runtimeId, String filesPath, String nat private native void passExceptionToJsNative(int runtimeId, Throwable ex, String message, String fullStackTrace, String jsStackTrace, boolean isDiscarded); - @CriticalNative - private static native int getCurrentRuntimeId(); + private static int getCurrentRuntimeId() { + if (USE_FAST_NATIVE_METHODS) { + return RuntimeNativeFast.getCurrentRuntimeId(); + } + + return getCurrentRuntimeIdLegacy(); + } + + private static native int getCurrentRuntimeIdLegacy(); + + public static int getPointerSize() { + if (USE_FAST_NATIVE_METHODS) { + return RuntimeNativeFast.getPointerSize(); + } + + return getPointerSizeLegacy(); + } + + private static native int getPointerSizeLegacy(); + + public static void SetManualInstrumentationMode(String mode) { + if (USE_FAST_NATIVE_METHODS) { + RuntimeNativeFast.SetManualInstrumentationMode(mode); + return; + } - @CriticalNative - public static native int getPointerSize(); + SetManualInstrumentationModeLegacy(mode); + } - @FastNative - public static native void SetManualInstrumentationMode(String mode); + private static native void SetManualInstrumentationModeLegacy(String mode); private static native void WorkerGlobalOnMessageCallback(int runtimeId, String message); diff --git a/test-app/runtime/src/main/java/com/tns/RuntimeNativeFast.java b/test-app/runtime/src/main/java/com/tns/RuntimeNativeFast.java new file mode 100644 index 000000000..9970c2c63 --- /dev/null +++ b/test-app/runtime/src/main/java/com/tns/RuntimeNativeFast.java @@ -0,0 +1,24 @@ +package com.tns; + +import dalvik.annotation.optimization.CriticalNative; +import dalvik.annotation.optimization.FastNative; + +final class RuntimeNativeFast { + private RuntimeNativeFast() { + } + + @CriticalNative + static native int generateNewObjectId(int runtimeId); + + @FastNative + static native boolean notifyGc(Runtime runtime, int runtimeId); + + @CriticalNative + static native int getCurrentRuntimeId(); + + @CriticalNative + static native int getPointerSize(); + + @FastNative + static native void SetManualInstrumentationMode(String mode); +}