diff options
Diffstat (limited to 'test')
| -rwxr-xr-x | test/071-dexfile-get-static-size/build | 30 | ||||
| -rw-r--r-- | test/071-dexfile-get-static-size/expected.txt | 4 | ||||
| -rw-r--r-- | test/071-dexfile-get-static-size/info.txt | 3 | ||||
| -rw-r--r-- | test/071-dexfile-get-static-size/src/Main.java | 62 | ||||
| -rw-r--r-- | test/071-dexfile-get-static-size/test1.dex | bin | 0 -> 1864 bytes | |||
| -rw-r--r-- | test/071-dexfile-get-static-size/test2.dex | bin | 0 -> 1264 bytes | |||
| -rw-r--r-- | test/655-jit-clinit/src/Main.java | 4 | ||||
| -rw-r--r-- | test/667-jit-jni-stub/expected.txt | 1 | ||||
| -rw-r--r-- | test/667-jit-jni-stub/info.txt | 1 | ||||
| -rw-r--r-- | test/667-jit-jni-stub/jit_jni_stub_test.cc | 63 | ||||
| -rwxr-xr-x | test/667-jit-jni-stub/run | 18 | ||||
| -rw-r--r-- | test/667-jit-jni-stub/src/Main.java | 180 | ||||
| -rw-r--r-- | test/Android.bp | 1 | ||||
| -rw-r--r-- | test/common/runtime_state.cc | 25 |
14 files changed, 105 insertions, 287 deletions
diff --git a/test/071-dexfile-get-static-size/build b/test/071-dexfile-get-static-size/build new file mode 100755 index 0000000000..0bba66d065 --- /dev/null +++ b/test/071-dexfile-get-static-size/build @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Copyright 2017 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. + +./default-build "$@" + +# Create and add as resources to the test jar file: +# 1. test1.dex +# 2. test2.dex +# 3. test-jar.jar, containing test1.dex as classes.dex +# 4. multi-jar.jar, containing test1.dex as classes.dex and test2.dex as classes2.dex +mkdir test-jar +cp test1.dex test-jar/classes.dex +cp test2.dex test-jar/classes2.dex +zip -j test-jar.jar test-jar/classes.dex +zip -j multi-jar.jar test-jar/classes.dex test-jar/classes2.dex +jar uf ${TEST_NAME}.jar test1.dex test2.dex test-jar.jar multi-jar.jar + diff --git a/test/071-dexfile-get-static-size/expected.txt b/test/071-dexfile-get-static-size/expected.txt new file mode 100644 index 0000000000..dfb77c3a2f --- /dev/null +++ b/test/071-dexfile-get-static-size/expected.txt @@ -0,0 +1,4 @@ +Size for test1.dex: 1864 +Size for test2.dex: 1264 +Size for test-jar.jar: 1864 +Size for multi-jar.jar: 3128 diff --git a/test/071-dexfile-get-static-size/info.txt b/test/071-dexfile-get-static-size/info.txt new file mode 100644 index 0000000000..5b528e81b4 --- /dev/null +++ b/test/071-dexfile-get-static-size/info.txt @@ -0,0 +1,3 @@ +Test DexFile.getStaticSizeOfDexFile API. + +test1.dex and test2.dex are arbitrary valid dex files. diff --git a/test/071-dexfile-get-static-size/src/Main.java b/test/071-dexfile-get-static-size/src/Main.java new file mode 100644 index 0000000000..4bf453801e --- /dev/null +++ b/test/071-dexfile-get-static-size/src/Main.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 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.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +public class Main { + private static void extractResource(String resource, String filename) throws Exception { + ClassLoader loader = Main.class.getClassLoader(); + InputStream is = loader.getResourceAsStream(resource); + OutputStream os = new FileOutputStream(filename); + int read; + byte[] buf = new byte[4096]; + while ((read = is.read(buf)) >= 0) { + os.write(buf, 0, read); + } + is.close(); + os.close(); + } + + private static long getDexFileSize(String filename) throws Exception { + ClassLoader loader = Main.class.getClassLoader(); + Class<?> DexFile = loader.loadClass("dalvik.system.DexFile"); + Method DexFile_loadDex = DexFile.getMethod("loadDex", + String.class, + String.class, + Integer.TYPE); + Method DexFile_getStaticSizeOfDexFile = DexFile.getMethod("getStaticSizeOfDexFile"); + Object dexFile = DexFile_loadDex.invoke(null, filename, null, 0); + return (Long) DexFile_getStaticSizeOfDexFile.invoke(dexFile); + } + + private static void test(String resource) throws Exception { + String filename = System.getenv("DEX_LOCATION") + "/" + resource; + extractResource(resource, filename); + long size = getDexFileSize(filename); + System.out.println("Size for " + resource + ": " + size); + } + + public static void main(String[] args) throws Exception { + test("test1.dex"); + test("test2.dex"); + test("test-jar.jar"); + test("multi-jar.jar"); + } +} diff --git a/test/071-dexfile-get-static-size/test1.dex b/test/071-dexfile-get-static-size/test1.dex Binary files differnew file mode 100644 index 0000000000..84602d03c2 --- /dev/null +++ b/test/071-dexfile-get-static-size/test1.dex diff --git a/test/071-dexfile-get-static-size/test2.dex b/test/071-dexfile-get-static-size/test2.dex Binary files differnew file mode 100644 index 0000000000..a07c46ef59 --- /dev/null +++ b/test/071-dexfile-get-static-size/test2.dex diff --git a/test/655-jit-clinit/src/Main.java b/test/655-jit-clinit/src/Main.java index 2fb8f2a86e..44b315478f 100644 --- a/test/655-jit-clinit/src/Main.java +++ b/test/655-jit-clinit/src/Main.java @@ -23,7 +23,7 @@ public class Main { Foo.hotMethod(); } - public native static boolean hasJitCompiledEntrypoint(Class<?> cls, String methodName); + public native static boolean isJitCompiled(Class<?> cls, String methodName); private native static boolean hasJit(); } @@ -36,7 +36,7 @@ class Foo { static { array = new Object[10000]; - while (!Main.hasJitCompiledEntrypoint(Foo.class, "hotMethod")) { + while (!Main.isJitCompiled(Foo.class, "hotMethod")) { Foo.hotMethod(); try { // Sleep to give a chance for the JIT to compile `hotMethod`. diff --git a/test/667-jit-jni-stub/expected.txt b/test/667-jit-jni-stub/expected.txt deleted file mode 100644 index 6a5618ebc6..0000000000 --- a/test/667-jit-jni-stub/expected.txt +++ /dev/null @@ -1 +0,0 @@ -JNI_OnLoad called diff --git a/test/667-jit-jni-stub/info.txt b/test/667-jit-jni-stub/info.txt deleted file mode 100644 index 6f25c44592..0000000000 --- a/test/667-jit-jni-stub/info.txt +++ /dev/null @@ -1 +0,0 @@ -Tests for JITting and collecting JNI stubs. diff --git a/test/667-jit-jni-stub/jit_jni_stub_test.cc b/test/667-jit-jni-stub/jit_jni_stub_test.cc deleted file mode 100644 index 82e06fc018..0000000000 --- a/test/667-jit-jni-stub/jit_jni_stub_test.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017 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 "jit/jit.h" -#include "jit/jit_code_cache.h" -#include "mirror/class.h" -#include "mirror/string.h" -#include "runtime.h" -#include "scoped_thread_state_change-inl.h" - -namespace art { - -// Local class declared as a friend of JitCodeCache so that we can access its internals. -class JitJniStubTestHelper { - public: - static bool isNextJitGcFull(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK(Runtime::Current()->GetJit() != nullptr); - jit::JitCodeCache* cache = Runtime::Current()->GetJit()->GetCodeCache(); - MutexLock mu(self, cache->lock_); - return cache->ShouldDoFullCollection(); - } -}; - -// Calls through to a static method with signature "()V". -extern "C" JNIEXPORT -void Java_Main_callThrough(JNIEnv* env, jclass, jclass klass, jstring methodName) { - ScopedObjectAccess soa(Thread::Current()); - std::string name = soa.Decode<mirror::String>(methodName)->ToModifiedUtf8(); - jmethodID method = env->GetStaticMethodID(klass, name.c_str(), "()V"); - CHECK(method != nullptr) << soa.Decode<mirror::Class>(klass)->PrettyDescriptor() << "." << name; - env->CallStaticVoidMethod(klass, method); -} - -extern "C" JNIEXPORT -void Java_Main_jitGc(JNIEnv*, jclass) { - CHECK(Runtime::Current()->GetJit() != nullptr); - jit::JitCodeCache* cache = Runtime::Current()->GetJit()->GetCodeCache(); - ScopedObjectAccess soa(Thread::Current()); - cache->GarbageCollectCache(Thread::Current()); -} - -extern "C" JNIEXPORT -jboolean Java_Main_isNextJitGcFull(JNIEnv*, jclass) { - ScopedObjectAccess soa(Thread::Current()); - return JitJniStubTestHelper::isNextJitGcFull(soa.Self()); -} - -} // namespace art diff --git a/test/667-jit-jni-stub/run b/test/667-jit-jni-stub/run deleted file mode 100755 index 1877be482e..0000000000 --- a/test/667-jit-jni-stub/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2017 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. - -# Disable AOT compilation of JNI stubs. -${RUN} "${@}" --no-prebuild --no-dex2oat diff --git a/test/667-jit-jni-stub/src/Main.java b/test/667-jit-jni-stub/src/Main.java deleted file mode 100644 index b867970eab..0000000000 --- a/test/667-jit-jni-stub/src/Main.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -public class Main { - public static void main(String[] args) throws Exception { - System.loadLibrary(args[0]); - if (isAotCompiled(Main.class, "hasJit")) { - throw new Error("This test must be run with --no-prebuild --no-dex2oat!"); - } - if (!hasJit()) { - return; - } - - testCompilationUseAndCollection(); - testMixedFramesOnStack(); - } - - public static void testCompilationUseAndCollection() { - // Test that callThrough() can be JIT-compiled. - assertFalse(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertFalse(hasJitCompiledCode(Main.class, "callThrough")); - ensureCompiledCallThroughEntrypoint(/* call */ true); - assertTrue(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - - // Use callThrough() once again now that the method has a JIT-compiled stub. - callThrough(Main.class, "doNothing"); - - // Test that GC with the JIT-compiled stub on the stack does not collect it. - // Also tests stack walk over the JIT-compiled stub. - callThrough(Main.class, "testGcWithCallThroughStubOnStack"); - - // Test that, when marking used methods before a full JIT GC, a single execution - // of the GenericJNI trampoline can save the compiled stub from being collected. - testSingleInvocationTriggersRecompilation(); - - // Test that the JNI compiled stub can actually be collected. - testStubCanBeCollected(); - } - - public static void testGcWithCallThroughStubOnStack() { - // Check that this method was called via JIT-compiled callThrough() stub. - assertTrue(hasJitCompiledEntrypoint(Main.class, "callThrough")); - // This assertion also exercises stack walk over the JIT-compiled callThrough() stub. - assertTrue(new Throwable().getStackTrace()[1].getMethodName().equals("callThrough")); - - doJitGcsUntilFullJitGcIsScheduled(); - // The callThrough() on the stack above this method is using the compiled stub, - // so the JIT GC should not remove the compiled code. - jitGc(); - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - } - - public static void testSingleInvocationTriggersRecompilation() { - // After scheduling a full JIT GC, single call through the GenericJNI - // trampoline should ensure that the compiled stub is used again. - doJitGcsUntilFullJitGcIsScheduled(); - callThrough(Main.class, "doNothing"); - ensureCompiledCallThroughEntrypoint(/* call */ false); // Wait for the compilation task to run. - assertTrue(hasJitCompiledEntrypoint(Main.class, "callThrough")); - jitGc(); // This JIT GC should not collect the callThrough() stub. - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - } - - public static void testMixedFramesOnStack() { - // Starts without a compiled JNI stub for callThrough(). - assertFalse(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertFalse(hasJitCompiledCode(Main.class, "callThrough")); - callThrough(Main.class, "testMixedFramesOnStackStage2"); - // We have just returned through the JIT-compiled JNI stub, so it must still - // be compiled (though not necessarily with the entrypoint pointing to it). - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - // Though the callThrough() is on the stack, that frame is using the GenericJNI - // and does not prevent the collection of the JNI stub. - testStubCanBeCollected(); - } - - public static void testMixedFramesOnStackStage2() { - // We cannot assert that callThrough() has no JIT compiled stub as that check - // may race against the compilation task. Just check the caller. - assertTrue(new Throwable().getStackTrace()[1].getMethodName().equals("callThrough")); - // Now ensure that the JNI stub is compiled and used. - ensureCompiledCallThroughEntrypoint(/* call */ true); - callThrough(Main.class, "testMixedFramesOnStackStage3"); - } - - public static void testMixedFramesOnStackStage3() { - // Check that this method was called via JIT-compiled callThrough() stub. - assertTrue(hasJitCompiledEntrypoint(Main.class, "callThrough")); - // This assertion also exercises stack walk over the JIT-compiled callThrough() stub. - assertTrue(new Throwable().getStackTrace()[1].getMethodName().equals("callThrough")); - // For a good measure, try a JIT GC. - jitGc(); - } - - public static void testStubCanBeCollected() { - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - doJitGcsUntilFullJitGcIsScheduled(); - assertFalse(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - jitGc(); // JIT GC without callThrough() on the stack should collect the callThrough() stub. - assertFalse(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertFalse(hasJitCompiledCode(Main.class, "callThrough")); - } - - public static void doJitGcsUntilFullJitGcIsScheduled() { - // We enter with a compiled stub for callThrough() but we also need the entrypoint to be set. - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - ensureCompiledCallThroughEntrypoint(/* call */ true); - // Perform JIT GC until the next GC is marked to do full collection. - do { - assertTrue(hasJitCompiledEntrypoint(Main.class, "callThrough")); - callThrough(Main.class, "jitGc"); // JIT GC with callThrough() safely on the stack. - } while (!isNextJitGcFull()); - // The JIT GC before the full collection resets entrypoints and waits to see - // if the methods are still in use. - assertFalse(hasJitCompiledEntrypoint(Main.class, "callThrough")); - assertTrue(hasJitCompiledCode(Main.class, "callThrough")); - } - - public static void ensureCompiledCallThroughEntrypoint(boolean call) { - int count = 0; - while (!hasJitCompiledEntrypoint(Main.class, "callThrough")) { - // If `call` is true, also exercise the `callThrough()` method to increase hotness. - int limit = call ? 1 << Math.min(count, 12) : 0; - for (int i = 0; i < limit; ++i) { - callThrough(Main.class, "doNothing"); - } - try { - // Sleep to give a chance for the JIT to compile `hasJit` stub. - Thread.sleep(100); - } catch (Exception e) { - // Ignore - } - if (++count == 50) { - throw new Error("TIMEOUT"); - } - }; - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new AssertionError("Expected true!"); - } - } - - public static void assertFalse(boolean value) { - if (value) { - throw new AssertionError("Expected false!"); - } - } - - public static void doNothing() { } - public static void throwError() { throw new Error(); } - - // Note that the callThrough()'s shorty differs from shorties of the other - // native methods used in this test because of the return type `void.` - public native static void callThrough(Class<?> cls, String methodName); - - public native static void jitGc(); - public native static boolean isNextJitGcFull(); - - public native static boolean isAotCompiled(Class<?> cls, String methodName); - public native static boolean hasJitCompiledEntrypoint(Class<?> cls, String methodName); - public native static boolean hasJitCompiledCode(Class<?> cls, String methodName); - private native static boolean hasJit(); -} diff --git a/test/Android.bp b/test/Android.bp index 01e424d5e3..ace62c23b8 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -385,7 +385,6 @@ cc_defaults { "656-annotation-lookup-generic-jni/test.cc", "661-oat-writer-layout/oat_writer_layout.cc", "664-aget-verifier/aget-verifier.cc", - "667-jit-jni-stub/jit_jni_stub_test.cc", "708-jit-cache-churn/jit.cc", ], shared_libs: [ diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index 34580800cc..df497c1181 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -152,10 +152,10 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env, return method->GetOatMethodQuickCode(kRuntimePointerSize) != nullptr; } -extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledEntrypoint(JNIEnv* env, - jclass, - jclass cls, - jstring method_name) { +extern "C" JNIEXPORT jboolean JNICALL Java_Main_isJitCompiled(JNIEnv* env, + jclass, + jclass cls, + jstring method_name) { jit::Jit* jit = GetJitIfEnabled(); if (jit == nullptr) { return false; @@ -169,23 +169,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledEntrypoint(JNIEnv* return jit->GetCodeCache()->ContainsPc(method->GetEntryPointFromQuickCompiledCode()); } -extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJitCompiledCode(JNIEnv* env, - jclass, - jclass cls, - jstring method_name) { - jit::Jit* jit = GetJitIfEnabled(); - if (jit == nullptr) { - return false; - } - Thread* self = Thread::Current(); - 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); - return jit->GetCodeCache()->ContainsMethod(method); -} - extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env, jclass, jclass cls, |