diff options
author | 2024-05-01 11:16:50 -0700 | |
---|---|---|
committer | 2024-05-01 13:33:32 -0700 | |
commit | aedf30b7a04413cb5d570edd8f1a31e1c9dfbf90 (patch) | |
tree | d459d4b449699240b074f02145f122dcfdf1a8ee /ravenwood/runtime-helper-src | |
parent | 70f58835f9bc7a2ad5004269939aa85bc1848a1f (diff) |
[Ravenwood] Support NativeAllocationRegistry
We don't track native allocation size, but we still need to
release native allocations.
Bug: 337110712
Test: atest RavenwoodBivalentTest
Test: atest RavenwoodBivalentTest_device
Test: ./ravenwood/scripts/run-ravenwood-tests.sh
Change-Id: Ia50c963731a26fc951a8040cbf353a5c56505b6a
Diffstat (limited to 'ravenwood/runtime-helper-src')
3 files changed, 187 insertions, 0 deletions
diff --git a/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp new file mode 100644 index 000000000000..8e3a21dd6d87 --- /dev/null +++ b/ravenwood/runtime-helper-src/jni/ravenwood_runtime.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 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 <nativehelper/JNIHelp.h> +#include "jni.h" +#include "utils/Log.h" +#include "utils/misc.h" + + +typedef void (*FreeFunction)(void*); + +static void NativeAllocationRegistry_applyFreeFunction(JNIEnv*, + jclass, + jlong freeFunction, + jlong ptr) { + void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr)); + FreeFunction nativeFreeFunction + = reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction)); + nativeFreeFunction(nativePtr); +} + +static const JNINativeMethod sMethods_NAR[] = +{ + { "applyFreeFunction", "(JJ)V", (void*)NativeAllocationRegistry_applyFreeFunction }, +}; + +extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) +{ + JNIEnv* env = NULL; + jint result = -1; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + ALOGE("GetEnv failed!"); + return result; + } + ALOG_ASSERT(env, "Could not retrieve the env!"); + + ALOGI("%s: JNI_OnLoad", __FILE__); + + // Initialize the Ravenwood version of NativeAllocationRegistry. + // We don't use this JNI on the device side, but if we ever have to do, skip this part. +#ifndef __ANDROID__ + int res = jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry", + sMethods_NAR, NELEM(sMethods_NAR)); + if (res < 0) { + return res; + } +#endif + + return JNI_VERSION_1_4; +} diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java new file mode 100644 index 000000000000..839b62a39471 --- /dev/null +++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/ravenwood/LibcoreRavenwoodUtils.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 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. + */ +package libcore.ravenwood; + +public class LibcoreRavenwoodUtils { + private LibcoreRavenwoodUtils() { + } + + public static void loadRavenwoodNativeRuntime() { + // TODO Stop using reflections. + // We need to call RavenwoodUtils.loadRavenwoodNativeRuntime(), but due to the build + // structure complexity, we can't refer to to this method directly from here, + // so let's use reflections for now... + try { + final var clazz = Class.forName("android.platform.test.ravenwood.RavenwoodUtils"); + final var method = clazz.getMethod("loadRavenwoodNativeRuntime"); + method.invoke(null); + } catch (Throwable th) { + throw new IllegalStateException("Failed to load Ravenwood native runtime", th); + } + } +} diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java new file mode 100644 index 000000000000..93861e87318f --- /dev/null +++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2024 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. + */ +package libcore.util; + +import libcore.ravenwood.LibcoreRavenwoodUtils; + +import java.lang.ref.Cleaner; +import java.lang.ref.Reference; + +/** + * Re-implementation of ART's NativeAllocationRegistry for Ravenwood. + * - We don't track the native allocation size on Ravenwood. + * - sun.misc.Cleaner isn't available on the desktop JVM, so we use java.lang.ref.Cleaner. + * (Should ART switch to java.lang.ref.Cleaner?) + */ +public class NativeAllocationRegistry { + static { + // Initialize the JNI method. + LibcoreRavenwoodUtils.loadRavenwoodNativeRuntime(); + } + + private final long mFreeFunction; + private static final Cleaner sCleaner = Cleaner.create(); + + public static NativeAllocationRegistry createNonmalloced( + ClassLoader classLoader, long freeFunction, long size) { + return new NativeAllocationRegistry(classLoader, freeFunction, size, false); + } + + public static NativeAllocationRegistry createMalloced( + ClassLoader classLoader, long freeFunction, long size) { + return new NativeAllocationRegistry(classLoader, freeFunction, size, true); + } + + public static NativeAllocationRegistry createMalloced( + ClassLoader classLoader, long freeFunction) { + return new NativeAllocationRegistry(classLoader, freeFunction, 0, true); + } + + public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) { + this(classLoader, freeFunction, size, size == 0); + } + + private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size, + boolean mallocAllocation) { + if (size < 0) { + throw new IllegalArgumentException("Invalid native allocation size: " + size); + } + mFreeFunction = freeFunction; + } + + public Runnable registerNativeAllocation(Object referent, long nativePtr) { + if (referent == null) { + throw new IllegalArgumentException("referent is null"); + } + if (nativePtr == 0) { + throw new IllegalArgumentException("nativePtr is null"); + } + + final Runnable releaser = () -> { + applyFreeFunction(mFreeFunction, nativePtr); + }; + sCleaner.register(referent, releaser); + + // Ensure that cleaner doesn't get invoked before we enable it. + Reference.reachabilityFence(referent); + return releaser; + } + + /** + * Calls {@code freeFunction}({@code nativePtr}). + */ + public static native void applyFreeFunction(long freeFunction, long nativePtr); +} + |