diff options
| author | 2024-12-31 15:30:27 +0000 | |
|---|---|---|
| committer | 2025-01-05 19:41:46 -0800 | |
| commit | 26040bb0286ca351158c675dcedd32bc85dd6dd1 (patch) | |
| tree | d4d81884db6a38d2311478ca5f8c6510532d2992 | |
| parent | 8842f9debe16fd1251cd6dbe16fd8c168098c61d (diff) | |
Add a test to check AOT code is used when method tracing is stopped
Adds a test to check that AOT code is restored when available when
method tracing is stopped.
Also updates isAotCompiled to work with more methods.
Bug: 303686344
Test: art/test.py -t 2286
Change-Id: I4b7abdeef4aa2bddb85e9cf86f3d844974b69dba
| -rw-r--r-- | test/2286-method-tracing-aot-code/expected-stderr.txt | 0 | ||||
| -rw-r--r-- | test/2286-method-tracing-aot-code/expected-stdout.txt | 1 | ||||
| -rw-r--r-- | test/2286-method-tracing-aot-code/info.txt | 1 | ||||
| -rw-r--r-- | test/2286-method-tracing-aot-code/src/Main.java | 124 | ||||
| -rw-r--r-- | test/common/runtime_state.cc | 29 |
5 files changed, 140 insertions, 15 deletions
diff --git a/test/2286-method-tracing-aot-code/expected-stderr.txt b/test/2286-method-tracing-aot-code/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2286-method-tracing-aot-code/expected-stderr.txt diff --git a/test/2286-method-tracing-aot-code/expected-stdout.txt b/test/2286-method-tracing-aot-code/expected-stdout.txt new file mode 100644 index 0000000000..6a5618ebc6 --- /dev/null +++ b/test/2286-method-tracing-aot-code/expected-stdout.txt @@ -0,0 +1 @@ +JNI_OnLoad called diff --git a/test/2286-method-tracing-aot-code/info.txt b/test/2286-method-tracing-aot-code/info.txt new file mode 100644 index 0000000000..2c5b5a42f7 --- /dev/null +++ b/test/2286-method-tracing-aot-code/info.txt @@ -0,0 +1 @@ +Tests that AOT code is used if available after tracing has stopped. diff --git a/test/2286-method-tracing-aot-code/src/Main.java b/test/2286-method-tracing-aot-code/src/Main.java new file mode 100644 index 0000000000..138f6fd11c --- /dev/null +++ b/test/2286-method-tracing-aot-code/src/Main.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2025 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. + */ + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; + +public class Main { + private static final String TEMP_FILE_NAME_PREFIX = "test"; + private static final String TEMP_FILE_NAME_SUFFIX = ".trace"; + private static File file; + + public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); + String name = System.getProperty("java.vm.name"); + if (!"Dalvik".equals(name)) { + System.out.println("This test is not supported on " + name); + return; + } + + if (VMDebug.getMethodTracingMode() != 0) { + VMDebug.$noinline$stopMethodTracing(); + } + + Main m = new Main(); + boolean isAot_main_before = isAotCompiled(Main.class, "main"); + boolean isAot_callOuter_before = isAotCompiled(Main.class, "callOuterFunction"); + + file = createTempFile(); + FileOutputStream out_file = new FileOutputStream(file); + VMDebug.startMethodTracing(file.getPath(), out_file.getFD(), /*buffer_size=*/0, /*flags=*/0, + /*sampling=*/false, /*sampling_interval*/ 0, /*streaming=*/true); + m.$noinline$doSomeWork(); + + VMDebug.$noinline$stopMethodTracing(); + out_file.close(); + file.delete(); + + boolean isAot_main_after = isAotCompiled(Main.class, "main"); + boolean isAot_callOuter_after = isAotCompiled(Main.class, "callOuterFunction"); + if (isAot_main_before != isAot_main_after) { + throw new Exception("AOT code for main not restored after method tracing? " + + isAot_main_before + " " + isAot_main_after); + } + + if (isAot_callOuter_before != isAot_callOuter_after) { + throw new Exception("AOT code for callOuter not restored after method tracing? " + + isAot_callOuter_before + " " + isAot_callOuter_after); + } + } + + private static File createTempFile() throws Exception { + try { + return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); + } catch (IOException e) { + System.setProperty("java.io.tmpdir", "/data/local/tmp"); + try { + return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); + } catch (IOException e2) { + System.setProperty("java.io.tmpdir", "/sdcard"); + return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); + } + } + } + + public void callOuterFunction() { + callLeafFunction(); + } + + public void callLeafFunction() {} + + public void $noinline$doSomeWork() { + callOuterFunction(); + callLeafFunction(); + } + + private static class VMDebug { + private static final Method startMethodTracingMethod; + private static final Method stopMethodTracingMethod; + private static final Method getMethodTracingModeMethod; + static { + try { + Class<?> c = Class.forName("dalvik.system.VMDebug"); + startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class, + FileDescriptor.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE, + Integer.TYPE, Boolean.TYPE); + stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing"); + getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void startMethodTracing(String filename, FileDescriptor fd, int bufferSize, + int flags, boolean samplingEnabled, int intervalUs, boolean streaming) + throws Exception { + startMethodTracingMethod.invoke( + null, filename, fd, bufferSize, flags, samplingEnabled, intervalUs, streaming); + } + public static void $noinline$stopMethodTracing() throws Exception { + stopMethodTracingMethod.invoke(null); + } + public static int getMethodTracingMode() throws Exception { + return (int) getMethodTracingModeMethod.invoke(null); + } + } + + private native static boolean isAotCompiled(Class<?> cls, String methodName); +} diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index c046e26755..6ff27f98f4 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -164,6 +164,19 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_compiledWithOptimizing(JNIEnv* e return JNI_TRUE; } +static ArtMethod* GetMethod(ScopedObjectAccess& soa, jclass cls, const ScopedUtfChars& chars) + REQUIRES_SHARED(Locks::mutator_lock_) { + CHECK(chars.c_str() != nullptr); + ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName( + chars.c_str(), kRuntimePointerSize); + if (method == nullptr) { + method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(chars.c_str(), + kRuntimePointerSize); + } + DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str(); + return method; +} + extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env, jclass, jclass cls, @@ -172,8 +185,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env, ScopedObjectAccess soa(self); ScopedUtfChars chars(env, method_name); CHECK(chars.c_str() != nullptr); - ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName( - chars.c_str(), kRuntimePointerSize); + ArtMethod* method = GetMethod(soa, cls, chars); const void* oat_code = method->GetOatMethodQuickCode(kRuntimePointerSize); if (oat_code == nullptr) { return false; @@ -182,19 +194,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env, return actual_code == oat_code; } -static ArtMethod* GetMethod(ScopedObjectAccess& soa, jclass cls, const ScopedUtfChars& chars) - REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK(chars.c_str() != nullptr); - ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName( - chars.c_str(), kRuntimePointerSize); - if (method == nullptr) { - method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName( - chars.c_str(), kRuntimePointerSize); - } - DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str(); - return method; -} - extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledEntrypoint(JNIEnv* env, jclass, jclass cls, |