diff options
Diffstat (limited to 'test')
48 files changed, 1774 insertions, 85 deletions
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build index faa298337c..56e87844c0 100644 --- a/test/003-omnibus-opcodes/build +++ b/test/003-omnibus-opcodes/build @@ -23,8 +23,8 @@ rm classes/UnresClass.class ${JAVAC} -d classes `find src2 -name '*.java'` if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else ${DX} -JXmx256m --debug --dex --output=classes.dex classes fi diff --git a/test/004-JniTest/expected.txt b/test/004-JniTest/expected.txt index 86ab37e1e5..155c6ae5f3 100644 --- a/test/004-JniTest/expected.txt +++ b/test/004-JniTest/expected.txt @@ -28,3 +28,30 @@ Subclass.<init> RUNNING sub object, sub class, sub nonstatic Subclass.nonstaticMethod PASSED sub object, sub class, sub nonstatic +Calling method ConcreteClass->JniCallNonOverridenDefaultMethod on object of type ConcreteClass +DefaultInterface.JniCallNonOverridenDefaultMethod +Calling method ConcreteClass->JniCallOverridenDefaultMethod on object of type ConcreteClass +ConcreteClass.JniCallOverridenDefaultMethod +Calling method ConcreteClass->JniCallOverridenDefaultMethodWithSuper on object of type ConcreteClass +ConcreteClass.JniCallOverridenDefaultMethodWithSuper +DefaultInterface.JniCallOverridenDefaultMethod +Calling method ConcreteClass->JniCallOverridenAbstractMethod on object of type ConcreteClass +ConcreteClass.JniCallOverridenAbstractMethod +Calling method ConcreteClass->JniCallConflictDefaultMethod on object of type ConcreteClass +EXCEPTION OCCURED: java.lang.IncompatibleClassChangeError: Conflicting default method implementations void ConflictInterface.JniCallConflictDefaultMethod() +Calling method ConcreteClass->JniCallSoftConflictMethod on object of type ConcreteClass +DefaultInterface.JniCallSoftConflictMethod +Calling method DefaultInterface->JniCallNonOverridenDefaultMethod on object of type ConcreteClass +DefaultInterface.JniCallNonOverridenDefaultMethod +Calling method DefaultInterface->JniCallOverridenDefaultMethod on object of type ConcreteClass +ConcreteClass.JniCallOverridenDefaultMethod +Calling method DefaultInterface->JniCallOverridenAbstractMethod on object of type ConcreteClass +ConcreteClass.JniCallOverridenAbstractMethod +Calling method DefaultInterface->JniCallConflictDefaultMethod on object of type ConcreteClass +EXCEPTION OCCURED: java.lang.IncompatibleClassChangeError: Conflicting default method implementations void ConflictInterface.JniCallConflictDefaultMethod() +Calling method DefaultInterface->JniCallSoftConflictMethod on object of type ConcreteClass +DefaultInterface.JniCallSoftConflictMethod +Calling method AbstractInterface->JniCallSoftConflictMethod on object of type ConcreteClass +DefaultInterface.JniCallSoftConflictMethod +Calling method ConflictInterface->JniCallConflictDefaultMethod on object of type ConcreteClass +EXCEPTION OCCURED: java.lang.IncompatibleClassChangeError: Conflicting default method implementations void ConflictInterface.JniCallConflictDefaultMethod() diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc index be7888b04a..f632331fe3 100644 --- a/test/004-JniTest/jni_test.cc +++ b/test/004-JniTest/jni_test.cc @@ -639,3 +639,85 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jcl extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) { return reinterpret_cast<jlong>(env->GetMethodID(c, "a", "()V")); } + +extern "C" JNIEXPORT void JNICALL Java_Main_enterJniCriticalSection(JNIEnv* env, jclass, + jint arraySize, + jbyteArray array0, + jbyteArray array1) { + for (int i = 0; i < 50000; ++i) { + char* data0 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array0, nullptr)); + char* data1 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array1, nullptr)); + bool up = i % 2 == 0; + for (int j = 0; j < arraySize; ++j) { + if (up) { + data1[j] = data0[j] + 1; + } else { + data0[j] = data1[j] + 1; + } + } + env->ReleasePrimitiveArrayCritical(array1, data1, 0); + env->ReleasePrimitiveArrayCritical(array0, data0, 0); + } +} + +class JniCallDefaultMethodsTest { + public: + explicit JniCallDefaultMethodsTest(JNIEnv* env) + : env_(env), concrete_class_(env_->FindClass("ConcreteClass")) { + assert(!env_->ExceptionCheck()); + assert(concrete_class_ != nullptr); + } + + void Test() { + TestCalls("ConcreteClass", { "JniCallNonOverridenDefaultMethod", + "JniCallOverridenDefaultMethod", + "JniCallOverridenDefaultMethodWithSuper", + "JniCallOverridenAbstractMethod", + "JniCallConflictDefaultMethod", + "JniCallSoftConflictMethod" }); + TestCalls("DefaultInterface", { "JniCallNonOverridenDefaultMethod", + "JniCallOverridenDefaultMethod", + "JniCallOverridenAbstractMethod", + "JniCallConflictDefaultMethod", + "JniCallSoftConflictMethod" }); + TestCalls("AbstractInterface", { "JniCallSoftConflictMethod" }); + TestCalls("ConflictInterface", { "JniCallConflictDefaultMethod" }); + } + + private: + void TestCalls(const char* declaring_class, std::vector<const char*> methods) { + jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>", "()V"); + jobject obj = env_->NewObject(concrete_class_, new_method); + assert(!env_->ExceptionCheck()); + assert(obj != nullptr); + jclass decl_class = env_->FindClass(declaring_class); + assert(!env_->ExceptionCheck()); + assert(decl_class != nullptr); + for (const char* method : methods) { + jmethodID method_id = env_->GetMethodID(decl_class, method, "()V"); + assert(!env_->ExceptionCheck()); + printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method); + env_->CallVoidMethod(obj, method_id); + if (env_->ExceptionCheck()) { + jthrowable thrown = env_->ExceptionOccurred(); + env_->ExceptionClear(); + jmethodID to_string = env_->GetMethodID( + env_->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); + jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string); + assert(!env_->ExceptionCheck()); + const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr); + assert(!env_->ExceptionCheck()); + assert(exception_string_utf8 != nullptr); + printf("EXCEPTION OCCURED: %s\n", exception_string_utf8); + env_->ReleaseStringUTFChars(exception_string, exception_string_utf8); + } + } + } + + JNIEnv* env_; + jclass concrete_class_; +}; + +extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) { + JniCallDefaultMethodsTest(env).Test(); +} diff --git a/test/004-JniTest/smali/AbstractInterface.smali b/test/004-JniTest/smali/AbstractInterface.smali new file mode 100644 index 0000000000..52b2fc537e --- /dev/null +++ b/test/004-JniTest/smali/AbstractInterface.smali @@ -0,0 +1,26 @@ +# /* +# * Copyright 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. +# */ + +.class public interface LAbstractInterface; +.super Ljava/lang/Object; + +# public interface AbstractInterface { +# public void JniCallSoftConflictMethod(); +# } + +.method public abstract JniCallSoftConflictMethod()V +.end method + diff --git a/test/004-JniTest/smali/ConcreteClass.smali b/test/004-JniTest/smali/ConcreteClass.smali new file mode 100644 index 0000000000..a9c072fc2f --- /dev/null +++ b/test/004-JniTest/smali/ConcreteClass.smali @@ -0,0 +1,72 @@ +# /* +# * Copyright 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. +# */ + +.class public LConcreteClass; +.super Ljava/lang/Object; +.implements LDefaultInterface; +.implements LConflictInterface; +.implements LAbstractInterface; + +# public class ConcreteClass implements DefaultInterface, ConflictInterface, AbstractInterface { +# public void JniCallOverridenAbstractMethod() { +# System.out.println("ConcreteClass.JniCallOverridenAbstractMethod"); +# } +# +# public void JniCallOverridenDefaultMethod() { +# System.out.println("ConcreteClass.JniCallOverridenDefaultMethod"); +# } +# +# public void JniCallOverridenDefaultMethodWithSuper() { +# System.out.println("ConcreteClass.JniCallOverridenDefaultMethodWithSuper"); +# DefaultInterface.super.JniCallOverridenDefaultMethod(); +# } +# } + +.method public constructor <init>()V + .registers 1 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method public JniCallOverridenAbstractMethod()V + .locals 2 + + const-string v0, "ConcreteClass.JniCallOverridenAbstractMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + +.method public JniCallOverridenDefaultMethod()V + .locals 2 + + const-string v0, "ConcreteClass.JniCallOverridenDefaultMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + +.method public JniCallOverridenDefaultMethodWithSuper()V + .locals 2 + + const-string v0, "ConcreteClass.JniCallOverridenDefaultMethodWithSuper" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + + invoke-super {p0}, LDefaultInterface;->JniCallOverridenDefaultMethod()V + + return-void +.end method diff --git a/test/004-JniTest/smali/ConflictInterface.smali b/test/004-JniTest/smali/ConflictInterface.smali new file mode 100644 index 0000000000..fc3d474df0 --- /dev/null +++ b/test/004-JniTest/smali/ConflictInterface.smali @@ -0,0 +1,35 @@ +# /* +# * Copyright 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. +# */ + +.class public interface LConflictInterface; +.super Ljava/lang/Object; + +# public interface ConflictInterface { +# public default void JniCallConflictDefaultMethod() { +# System.out.println("ConflictInterface.JniCallConflictDefaultMethod"); +# } +# +# } + +.method public JniCallConflictDefaultMethod()V + .locals 2 + + const-string v0, "ConflictInterface.JniCallConflictDefaultMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + diff --git a/test/004-JniTest/smali/DefaultInterface.smali b/test/004-JniTest/smali/DefaultInterface.smali new file mode 100644 index 0000000000..1ee872154b --- /dev/null +++ b/test/004-JniTest/smali/DefaultInterface.smali @@ -0,0 +1,77 @@ +# /* +# * Copyright 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. +# */ + +.class public interface LDefaultInterface; +.super Ljava/lang/Object; + +# public interface DefaultInterface { +# public default void JniCallNonOverridenDefaultMethod() { +# System.out.println("DefaultInterface.JniCallNonOverridenDefaultMethod"); +# } +# +# public default void JniCallOverridenDefaultMethod() { +# System.out.println("DefaultInterface.JniCallOverridenDefaultMethod"); +# } +# +# public void JniCallOverridenAbstractMethod(); +# +# public default void JniCallConflictDefaultMethod() { +# System.out.println("DefaultInterface.JniCallConflictDefaultMethod"); +# } +# +# public default void JniCallSoftConflictMethod() { +# System.out.println("DefaultInterface.JniCallSoftConflictMethod"); +# } +# } + +.method public JniCallNonOverridenDefaultMethod()V + .locals 2 + + const-string v0, "DefaultInterface.JniCallNonOverridenDefaultMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + +.method public JniCallOverridenDefaultMethod()V + .locals 2 + + const-string v0, "DefaultInterface.JniCallOverridenDefaultMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + +.method public abstract JniCallOverridenAbstractMethod()V +.end method + +.method public JniCallConflictDefaultMethod()V + .locals 2 + + const-string v0, "DefaultInterface.JniCallConflictDefaultMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method + +.method public JniCallSoftConflictMethod()V + .locals 2 + + const-string v0, "DefaultInterface.JniCallSoftConflictMethod" + sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V + return-void +.end method diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java index ee3a3b9830..9f4a8522e7 100644 --- a/test/004-JniTest/src/Main.java +++ b/test/004-JniTest/src/Main.java @@ -38,8 +38,12 @@ public class Main { testNewStringObject(); testRemoveLocalObject(); testProxyGetMethodID(); + testJniCriticalSectionAndGc(); + testCallDefaultMethods(); } + private static native void testCallDefaultMethods(); + private static native void testFindClassOnAttachedNativeThread(); private static boolean testFindFieldOnAttachedNativeThreadField; @@ -120,7 +124,7 @@ public class Main { private static void testRemoveLocalObject() { removeLocalObject(new Object()); } - + private static native short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7, short s8, short s9, short s10); @@ -222,6 +226,35 @@ public class Main { } private static native long testGetMethodID(Class<?> c); + + // Exercise GC and JNI critical sections in parallel. + private static void testJniCriticalSectionAndGc() { + Thread runGcThread = new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; ++i) { + Runtime.getRuntime().gc(); + } + } + }); + Thread jniCriticalThread = new Thread(new Runnable() { + @Override + public void run() { + final int arraySize = 32; + byte[] array0 = new byte[arraySize]; + byte[] array1 = new byte[arraySize]; + enterJniCriticalSection(arraySize, array0, array1); + } + }); + jniCriticalThread.start(); + runGcThread.start(); + try { + jniCriticalThread.join(); + runGcThread.join(); + } catch (InterruptedException ignored) {} + } + + private static native void enterJniCriticalSection(int arraySize, byte[] array0, byte[] array); } class JniCallNonvirtualTest { diff --git a/test/005-annotations/build b/test/005-annotations/build index 057b351dab..93bee507df 100644 --- a/test/005-annotations/build +++ b/test/005-annotations/build @@ -29,8 +29,8 @@ rm 'classes/android/test/anno/MissingAnnotation.class' rm 'classes/android/test/anno/ClassWithInnerAnnotationClass$MissingInnerAnnotationClass.class' if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else ${DX} -JXmx256m --debug --dex --output=classes.dex classes fi diff --git a/test/022-interface/build b/test/022-interface/build index 3f8915c27e..5cfc7f25b7 100644 --- a/test/022-interface/build +++ b/test/022-interface/build @@ -20,8 +20,8 @@ set -e # Use classes that are compiled with ecj that exposes an invokeinterface # issue when interfaces override methods in Object if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes fi diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java index af25d9bc54..e5c9dba63f 100644 --- a/test/082-inline-execute/src/Main.java +++ b/test/082-inline-execute/src/Main.java @@ -804,6 +804,7 @@ public class Main { Assert.assertEquals(Math.round(-2.9d), -3l); Assert.assertEquals(Math.round(-3.0d), -3l); Assert.assertEquals(Math.round(0.49999999999999994d), 0l); + Assert.assertEquals(Math.round(9007199254740991.0d), 9007199254740991l); // 2^53 - 1 Assert.assertEquals(Math.round(Double.NaN), (long)+0.0d); Assert.assertEquals(Math.round(Long.MAX_VALUE + 1.0d), Long.MAX_VALUE); Assert.assertEquals(Math.round(Long.MIN_VALUE - 1.0d), Long.MIN_VALUE); @@ -825,6 +826,7 @@ public class Main { Assert.assertEquals(Math.round(-2.5f), -2); Assert.assertEquals(Math.round(-2.9f), -3); Assert.assertEquals(Math.round(-3.0f), -3); + Assert.assertEquals(Math.round(16777215.0f), 16777215); // 2^24 - 1 Assert.assertEquals(Math.round(Float.NaN), (int)+0.0f); Assert.assertEquals(Math.round(Integer.MAX_VALUE + 1.0f), Integer.MAX_VALUE); Assert.assertEquals(Math.round(Integer.MIN_VALUE - 1.0f), Integer.MIN_VALUE); diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build index 6f50a76863..21dc66269d 100644 --- a/test/085-old-style-inner-class/build +++ b/test/085-old-style-inner-class/build @@ -23,8 +23,8 @@ mkdir classes ${JAVAC} -source 1.4 -target 1.4 -d classes `find src -name '*.java'` if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else # Suppress stderr to keep the inner class warnings out of the expected output. ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes 2>/dev/null diff --git a/test/091-override-package-private-method/build b/test/091-override-package-private-method/build index 5a340dcf6d..073a4ba9bc 100755 --- a/test/091-override-package-private-method/build +++ b/test/091-override-package-private-method/build @@ -24,14 +24,12 @@ mkdir classes-ex mv classes/OverridePackagePrivateMethodSuper.class classes-ex if [ ${USE_JACK} = "true" ]; then - # Create .jack files from classes generated with javac. - ${JILL} classes --output classes.jack - ${JILL} classes-ex --output classes-ex.jack + jar cf classes.jill.jar -C classes . + jar cf classes-ex.jill.jar -C classes-ex . - # Create DEX files from .jack files. - ${JACK} --import classes.jack --output-dex . + ${JACK} --import classes.jill.jar --output-dex . zip $TEST_NAME.jar classes.dex - ${JACK} --import classes-ex.jack --output-dex . + ${JACK} --import classes-ex.jill.jar --output-dex . zip ${TEST_NAME}-ex.jar classes.dex else if [ ${NEED_DEX} = "true" ]; then diff --git a/test/097-duplicate-method/build b/test/097-duplicate-method/build index a8558739de..4525549905 100644 --- a/test/097-duplicate-method/build +++ b/test/097-duplicate-method/build @@ -23,10 +23,10 @@ if [ ${USE_JACK} = "true" ]; then ${JACK} --output-jack src.jack src ${JASMIN} -d classes src/*.j - ${JILL} classes --output jasmin.jack + jar cf jasmin.jill.jar -C classes . # We set jack.import.type.policy=keep-first to consider class definitions from jasmin first. - ${JACK} --import jasmin.jack --import src.jack -D jack.import.type.policy=keep-first --output-dex . + ${JACK} --import jasmin.jill.jar --import src.jack -D jack.import.type.policy=keep-first --output-dex . else ${JAVAC} -d classes src/*.java ${JASMIN} -d classes src/*.j diff --git a/test/111-unresolvable-exception/build b/test/111-unresolvable-exception/build index e772fb812f..58ac26d836 100644 --- a/test/111-unresolvable-exception/build +++ b/test/111-unresolvable-exception/build @@ -22,8 +22,8 @@ ${JAVAC} -d classes `find src -name '*.java'` rm classes/TestException.class if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes fi diff --git a/test/113-multidex/build b/test/113-multidex/build index 8ef5c0eb0f..4557ccd22a 100644 --- a/test/113-multidex/build +++ b/test/113-multidex/build @@ -28,14 +28,12 @@ ${JAVAC} -d classes2 `find src -name '*.java'` rm classes2/Second.class classes2/FillerA.class classes2/FillerB.class classes2/Inf*.class if [ ${USE_JACK} = "true" ]; then - # Create .jack files from classes generated with javac. - ${JILL} classes --output classes.jack - ${JILL} classes2 --output classes2.jack + jar cf classes.jill.jar -C classes . + jar cf classes2.jill.jar -C classes2 . - # Create DEX files from .jack files. - ${JACK} --import classes.jack --output-dex . + ${JACK} --import classes.jill.jar --output-dex . mv classes.dex classes-1.dex - ${JACK} --import classes2.jack --output-dex . + ${JACK} --import classes2.jill.jar --output-dex . mv classes.dex classes2.dex mv classes-1.dex classes.dex else diff --git a/test/121-modifiers/build b/test/121-modifiers/build index 85b69e92a6..771dd51829 100644 --- a/test/121-modifiers/build +++ b/test/121-modifiers/build @@ -31,9 +31,9 @@ set -e # mv Main.class A.class A\$B.class A\$C.class classes/ if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack + jar cf classes.jill.jar -C classes . # Workaround b/19561685: disable sanity checks to produce a DEX file with invalid modifiers. - ${JACK} --sanity-checks off --import classes.jack --output-dex . + ${JACK} --sanity-checks off --import classes.jill.jar --output-dex . else ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes fi diff --git a/test/124-missing-classes/build b/test/124-missing-classes/build index b92ecf9382..0a340a26d6 100644 --- a/test/124-missing-classes/build +++ b/test/124-missing-classes/build @@ -27,8 +27,8 @@ rm 'classes/MissingClass.class' rm 'classes/Main$MissingInnerClass.class' if [ ${USE_JACK} = "true" ]; then - ${JILL} classes --output classes.jack - ${JACK} --import classes.jack --output-dex . + jar cf classes.jill.jar -C classes . + ${JACK} --import classes.jill.jar --output-dex . else ${DX} -JXmx256m --debug --dex --output=classes.dex classes fi diff --git a/test/126-miranda-multidex/build b/test/126-miranda-multidex/build index b7f2118d2f..00b9ba0ac2 100644 --- a/test/126-miranda-multidex/build +++ b/test/126-miranda-multidex/build @@ -28,14 +28,12 @@ ${JAVAC} -d classes2 `find src -name '*.java'` rm classes2/Main.class classes2/MirandaAbstract.class classes2/MirandaClass*.class classes2/MirandaInterface2*.class if [ ${USE_JACK} = "true" ]; then - # Create .jack files from classes generated with javac. - ${JILL} classes --output classes.jack - ${JILL} classes2 --output classes2.jack + jar cf classes.jill.jar -C classes . + jar cf classes2.jill.jar -C classes2 . - # Create DEX files from .jack files. - ${JACK} --import classes.jack --output-dex . + ${JACK} --import classes.jill.jar --output-dex . mv classes.dex classes-1.dex - ${JACK} --import classes2.jack --output-dex . + ${JACK} --import classes2.jill.jar --output-dex . mv classes.dex classes2.dex mv classes-1.dex classes.dex else diff --git a/test/127-checker-secondarydex/build b/test/127-checker-secondarydex/build index 0d9f4d6291..7ce46acfed 100755 --- a/test/127-checker-secondarydex/build +++ b/test/127-checker-secondarydex/build @@ -24,14 +24,12 @@ mkdir classes-ex mv classes/Super.class classes-ex if [ ${USE_JACK} = "true" ]; then - # Create .jack files from classes generated with javac. - ${JILL} classes --output classes.jack - ${JILL} classes-ex --output classes-ex.jack + jar cf classes.jill.jar -C classes . + jar cf classes-ex.jill.jar -C classes-ex . - # Create DEX files from .jack files. - ${JACK} --import classes.jack --output-dex . + ${JACK} --import classes.jill.jar --output-dex . zip $TEST_NAME.jar classes.dex - ${JACK} --import classes-ex.jack --output-dex . + ${JACK} --import classes-ex.jill.jar --output-dex . zip ${TEST_NAME}-ex.jar classes.dex else if [ ${NEED_DEX} = "true" ]; then diff --git a/test/130-hprof/src-ex/Allocator.java b/test/130-hprof/src-ex/Allocator.java new file mode 100644 index 0000000000..ee75a14f30 --- /dev/null +++ b/test/130-hprof/src-ex/Allocator.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +// Simple allocator that returns a boot class path object. +public class Allocator { + public static Object allocObject() { + return new Object(); + } +} diff --git a/test/130-hprof/src/Main.java b/test/130-hprof/src/Main.java index 67e52323dd..9868c617f5 100644 --- a/test/130-hprof/src/Main.java +++ b/test/130-hprof/src/Main.java @@ -16,6 +16,7 @@ import java.io.File; import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; @@ -34,24 +35,21 @@ public class Main { } } - public static void main(String[] args) { - // Create some data. - Object data[] = new Object[TEST_LENGTH]; - for (int i = 0; i < data.length; i++) { - if (makeArray(i)) { - data[i] = new Object[TEST_LENGTH]; - } else { - data[i] = String.valueOf(i); - } + private static Object allocInDifferentLoader() throws Exception { + final String DEX_FILE = System.getenv("DEX_LOCATION") + "/130-hprof-ex.jar"; + Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader"); + if (pathClassLoader == null) { + throw new AssertionError("Couldn't find path class loader class"); } - for (int i = 0; i < data.length; i++) { - if (makeArray(i)) { - Object data2[] = (Object[]) data[i]; - fillArray(data, data2, i); - } - } - System.out.println("Generated data."); + Constructor constructor = + pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class); + ClassLoader loader = (ClassLoader)constructor.newInstance( + DEX_FILE, ClassLoader.getSystemClassLoader()); + Class allocator = loader.loadClass("Allocator"); + return allocator.getDeclaredMethod("allocObject", null).invoke(null); + } + private static void createDumpAndConv() throws RuntimeException { File dumpFile = null; File convFile = null; @@ -88,6 +86,43 @@ public class Main { } } + public static void main(String[] args) throws Exception { + // Create some data. + Object data[] = new Object[TEST_LENGTH]; + for (int i = 0; i < data.length; i++) { + if (makeArray(i)) { + data[i] = new Object[TEST_LENGTH]; + } else { + data[i] = String.valueOf(i); + } + } + for (int i = 0; i < data.length; i++) { + if (makeArray(i)) { + Object data2[] = (Object[]) data[i]; + fillArray(data, data2, i); + } + } + System.out.println("Generated data."); + + createDumpAndConv(); + Class klass = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal"); + if (klass == null) { + throw new AssertionError("Couldn't find path class loader class"); + } + Method enableMethod = klass.getDeclaredMethod("enableRecentAllocations", + Boolean.TYPE); + if (enableMethod == null) { + throw new AssertionError("Couldn't find path class loader class"); + } + enableMethod.invoke(null, true); + Object o = allocInDifferentLoader(); + // Run GC to cause class unloading. + Runtime.getRuntime().gc(); + createDumpAndConv(); + // TODO: Somehow check contents of hprof file. + enableMethod.invoke(null, false); + } + private static File getHprofConf() { // Use the java.library.path. It points to the lib directory. File libDir = new File(System.getProperty("java.library.path")); diff --git a/test/442-checker-constant-folding/smali/TestCmp.smali b/test/442-checker-constant-folding/smali/TestCmp.smali new file mode 100644 index 0000000000..df631bc202 --- /dev/null +++ b/test/442-checker-constant-folding/smali/TestCmp.smali @@ -0,0 +1,332 @@ +# Copyright (C) 2015 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. + +.class public LTestCmp; + +.super Ljava/lang/Object; + + +## CHECK-START: int TestCmp.$opt$CmpLongConstants() constant_folding (before) +## CHECK-DAG: <<Const13:j\d+>> LongConstant 13 +## CHECK-DAG: <<Const7:j\d+>> LongConstant 7 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const13>>,<<Const7>>] +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLongConstants() constant_folding (after) +## CHECK-DAG: LongConstant 13 +## CHECK-DAG: LongConstant 7 +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: Return [<<Const1>>] + +## CHECK-START: int TestCmp.$opt$CmpLongConstants() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLongConstants()I + .registers 5 + const-wide v1, 13 + const-wide v3, 7 + cmp-long v0, v1, v3 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstants() constant_folding (before) +## CHECK-DAG: <<Const11:f\d+>> FloatConstant 11 +## CHECK-DAG: <<Const22:f\d+>> FloatConstant 22 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const11>>,<<Const22>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstants() constant_folding (after) +## CHECK-DAG: FloatConstant 11 +## CHECK-DAG: FloatConstant 22 +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstants() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtFloatConstants()I + .registers 3 + const v1, 11.f + const v2, 22.f + cmpg-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstants() constant_folding (before) +## CHECK-DAG: <<Const33:f\d+>> FloatConstant 33 +## CHECK-DAG: <<Const44:f\d+>> FloatConstant 44 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const33>>,<<Const44>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstants() constant_folding (after) +## CHECK-DAG: FloatConstant 33 +## CHECK-DAG: FloatConstant 44 +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstants() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtFloatConstants()I + .registers 3 + const v1, 33.f + const v2, 44.f + cmpl-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstants() constant_folding (before) +## CHECK-DAG: <<Const55:d\d+>> DoubleConstant 55 +## CHECK-DAG: <<Const66:d\d+>> DoubleConstant 66 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const55>>,<<Const66>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstants() constant_folding (after) +## CHECK-DAG: DoubleConstant 55 +## CHECK-DAG: DoubleConstant 66 +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstants() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtDoubleConstants()I + .registers 5 + const-wide v1, 55. + const-wide v3, 66. + cmpg-double v0, v1, v3 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstants() constant_folding (before) +## CHECK-DAG: <<Const77:d\d+>> DoubleConstant 77 +## CHECK-DAG: <<Const88:d\d+>> DoubleConstant 88 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const77>>,<<Const88>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstants() constant_folding (after) +## CHECK-DAG: DoubleConstant 77 +## CHECK-DAG: DoubleConstant 88 +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstants() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtDoubleConstants()I + .registers 5 + const-wide v1, 77. + const-wide v3, 88. + cmpl-double v0, v1, v3 + return v0 +.end method + + +## CHECK-START: int TestCmp.$opt$CmpLongSameConstant() constant_folding (before) +## CHECK-DAG: <<Const100:j\d+>> LongConstant 100 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const100>>,<<Const100>>] +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLongSameConstant() constant_folding (after) +## CHECK-DAG: LongConstant 100 +## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 +## CHECK-DAG: Return [<<Const0>>] + +## CHECK-START: int TestCmp.$opt$CmpLongSameConstant() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLongSameConstant()I + .registers 5 + const-wide v1, 100 + const-wide v3, 100 + cmp-long v0, v1, v3 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpGtFloatSameConstant() constant_folding (before) +## CHECK-DAG: <<Const200:f\d+>> FloatConstant 200 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const200>>,<<Const200>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatSameConstant() constant_folding (after) +## CHECK-DAG: FloatConstant 200 +## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 +## CHECK-DAG: Return [<<Const0>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatSameConstant() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtFloatSameConstant()I + .registers 3 + const v1, 200.f + const v2, 200.f + cmpg-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtFloatSameConstant() constant_folding (before) +## CHECK-DAG: <<Const300:f\d+>> FloatConstant 300 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const300>>,<<Const300>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatSameConstant() constant_folding (after) +## CHECK-DAG: FloatConstant 300 +## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 +## CHECK-DAG: Return [<<Const0>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatSameConstant() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtFloatSameConstant()I + .registers 3 + const v1, 300.f + const v2, 300.f + cmpl-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleSameConstant() constant_folding (before) +## CHECK-DAG: <<Const400:d\d+>> DoubleConstant 400 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const400>>,<<Const400>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleSameConstant() constant_folding (after) +## CHECK-DAG: DoubleConstant 400 +## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 +## CHECK-DAG: Return [<<Const0>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleSameConstant() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtDoubleSameConstant()I + .registers 5 + const-wide v1, 400. + const-wide v3, 400. + cmpg-double v0, v1, v3 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleSameConstant() constant_folding (before) +## CHECK-DAG: <<Const500:d\d+>> DoubleConstant 500 +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const500>>,<<Const500>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleSameConstant() constant_folding (after) +## CHECK-DAG: DoubleConstant 500 +## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 +## CHECK-DAG: Return [<<Const0>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleSameConstant() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtDoubleSameConstant()I + .registers 5 + const-wide v1, 500. + const-wide v3, 500. + cmpl-double v0, v1, v3 + return v0 +.end method + + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstantWithNaN() constant_folding (before) +## CHECK-DAG: <<Const44:f\d+>> FloatConstant 44 +## CHECK-DAG: <<ConstNan:f\d+>> FloatConstant nan +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const44>>,<<ConstNan>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstantWithNaN() constant_folding (after) +## CHECK-DAG: FloatConstant 44 +## CHECK-DAG: FloatConstant nan +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: Return [<<Const1>>] + +## CHECK-START: int TestCmp.$opt$CmpGtFloatConstantWithNaN() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtFloatConstantWithNaN()I + .registers 3 + const v1, 44.f + const v2, NaNf + cmpg-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstantWithNaN() constant_folding (before) +## CHECK-DAG: <<Const44:f\d+>> FloatConstant 44 +## CHECK-DAG: <<ConstNan:f\d+>> FloatConstant nan +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const44>>,<<ConstNan>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstantWithNaN() constant_folding (after) +## CHECK-DAG: FloatConstant 44 +## CHECK-DAG: FloatConstant nan +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpLtFloatConstantWithNaN() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtFloatConstantWithNaN()I + .registers 3 + const v1, 44.f + const v2, NaNf + cmpl-float v0, v1, v2 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstantWithNaN() constant_folding (before) +## CHECK-DAG: <<Const45:d\d+>> DoubleConstant 45 +## CHECK-DAG: <<ConstNan:d\d+>> DoubleConstant nan +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const45>>,<<ConstNan>>] bias:gt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstantWithNaN() constant_folding (after) +## CHECK-DAG: DoubleConstant 45 +## CHECK-DAG: DoubleConstant nan +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: Return [<<Const1>>] + +## CHECK-START: int TestCmp.$opt$CmpGtDoubleConstantWithNaN() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpGtDoubleConstantWithNaN()I + .registers 5 + const-wide v1, 45. + const-wide v3, NaN + cmpg-double v0, v1, v3 + return v0 +.end method + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstantWithNaN() constant_folding (before) +## CHECK-DAG: <<Const46:d\d+>> DoubleConstant 46 +## CHECK-DAG: <<ConstNan:d\d+>> DoubleConstant nan +## CHECK-DAG: <<Cmp:i\d+>> Compare [<<Const46>>,<<ConstNan>>] bias:lt +## CHECK-DAG: Return [<<Cmp>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstantWithNaN() constant_folding (after) +## CHECK-DAG: DoubleConstant 46 +## CHECK-DAG: DoubleConstant nan +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: Return [<<ConstM1>>] + +## CHECK-START: int TestCmp.$opt$CmpLtDoubleConstantWithNaN() constant_folding (after) +## CHECK-NOT: Compare + +.method public static $opt$CmpLtDoubleConstantWithNaN()I + .registers 5 + const-wide v1, 46. + const-wide v3, NaN + cmpl-double v0, v1, v3 + return v0 +.end method diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index 5479818ae7..93fe397273 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -14,8 +14,13 @@ * limitations under the License. */ +import java.lang.reflect.Method; + public class Main { + // Workaround for b/18051191. + class InnerClass {} + public static void assertFalse(boolean condition) { if (condition) { throw new Error(); @@ -47,6 +52,68 @@ public class Main { } + // Wrappers around methods located in file TestCmp.smali. + + public int smaliCmpLongConstants() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLongConstants"); + return (Integer)m.invoke(null); + } + public int smaliCmpGtFloatConstants() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtFloatConstants"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtFloatConstants() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtFloatConstants"); + return (Integer)m.invoke(null); + } + public int smaliCmpGtDoubleConstants() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtDoubleConstants"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtDoubleConstants() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtDoubleConstants"); + return (Integer)m.invoke(null); + } + + public int smaliCmpLongSameConstant() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLongSameConstant"); + return (Integer)m.invoke(null); + } + public int smaliCmpGtFloatSameConstant() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtFloatSameConstant"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtFloatSameConstant() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtFloatSameConstant"); + return (Integer)m.invoke(null); + } + public int smaliCmpGtDoubleSameConstant() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtDoubleSameConstant"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtDoubleSameConstant() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtDoubleSameConstant"); + return (Integer)m.invoke(null); + } + + public int smaliCmpGtFloatConstantWithNaN() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtFloatConstantWithNaN"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtFloatConstantWithNaN() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtFloatConstantWithNaN"); + return (Integer)m.invoke(null); + } + public int smaliCmpGtDoubleConstantWithNaN() throws Exception { + Method m = testCmp.getMethod("$opt$CmpGtDoubleConstantWithNaN"); + return (Integer)m.invoke(null); + } + public int smaliCmpLtDoubleConstantWithNaN() throws Exception { + Method m = testCmp.getMethod("$opt$CmpLtDoubleConstantWithNaN"); + return (Integer)m.invoke(null); + } + + /** * Exercise constant folding on negation. */ @@ -89,6 +156,44 @@ public class Main { return y; } + /// CHECK-START: float Main.FloatNegation() constant_folding (before) + /// CHECK-DAG: <<Const42:f\d+>> FloatConstant 42 + /// CHECK-DAG: <<Neg:f\d+>> Neg [<<Const42>>] + /// CHECK-DAG: Return [<<Neg>>] + + /// CHECK-START: float Main.FloatNegation() constant_folding (after) + /// CHECK-DAG: <<ConstN42:f\d+>> FloatConstant -42 + /// CHECK-DAG: Return [<<ConstN42>>] + + /// CHECK-START: float Main.FloatNegation() constant_folding (after) + /// CHECK-NOT: Neg + + public static float FloatNegation() { + float x, y; + x = 42F; + y = -x; + return y; + } + + /// CHECK-START: double Main.DoubleNegation() constant_folding (before) + /// CHECK-DAG: <<Const42:d\d+>> DoubleConstant 42 + /// CHECK-DAG: <<Neg:d\d+>> Neg [<<Const42>>] + /// CHECK-DAG: Return [<<Neg>>] + + /// CHECK-START: double Main.DoubleNegation() constant_folding (after) + /// CHECK-DAG: <<ConstN42:d\d+>> DoubleConstant -42 + /// CHECK-DAG: Return [<<ConstN42>>] + + /// CHECK-START: double Main.DoubleNegation() constant_folding (after) + /// CHECK-NOT: Neg + + public static double DoubleNegation() { + double x, y; + x = 42D; + y = -x; + return y; + } + /** * Exercise constant folding on addition. @@ -166,6 +271,48 @@ public class Main { return c; } + /// CHECK-START: float Main.FloatAddition() constant_folding (before) + /// CHECK-DAG: <<Const1:f\d+>> FloatConstant 1 + /// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2 + /// CHECK-DAG: <<Add:f\d+>> Add [<<Const1>>,<<Const2>>] + /// CHECK-DAG: Return [<<Add>>] + + /// CHECK-START: float Main.FloatAddition() constant_folding (after) + /// CHECK-DAG: <<Const3:f\d+>> FloatConstant 3 + /// CHECK-DAG: Return [<<Const3>>] + + /// CHECK-START: float Main.FloatAddition() constant_folding (after) + /// CHECK-NOT: Add + + public static float FloatAddition() { + float a, b, c; + a = 1F; + b = 2F; + c = a + b; + return c; + } + + /// CHECK-START: double Main.DoubleAddition() constant_folding (before) + /// CHECK-DAG: <<Const1:d\d+>> DoubleConstant 1 + /// CHECK-DAG: <<Const2:d\d+>> DoubleConstant 2 + /// CHECK-DAG: <<Add:d\d+>> Add [<<Const1>>,<<Const2>>] + /// CHECK-DAG: Return [<<Add>>] + + /// CHECK-START: double Main.DoubleAddition() constant_folding (after) + /// CHECK-DAG: <<Const3:d\d+>> DoubleConstant 3 + /// CHECK-DAG: Return [<<Const3>>] + + /// CHECK-START: double Main.DoubleAddition() constant_folding (after) + /// CHECK-NOT: Add + + public static double DoubleAddition() { + double a, b, c; + a = 1D; + b = 2D; + c = a + b; + return c; + } + /** * Exercise constant folding on subtraction. @@ -213,6 +360,48 @@ public class Main { return c; } + /// CHECK-START: float Main.FloatSubtraction() constant_folding (before) + /// CHECK-DAG: <<Const6:f\d+>> FloatConstant 6 + /// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2 + /// CHECK-DAG: <<Sub:f\d+>> Sub [<<Const6>>,<<Const2>>] + /// CHECK-DAG: Return [<<Sub>>] + + /// CHECK-START: float Main.FloatSubtraction() constant_folding (after) + /// CHECK-DAG: <<Const4:f\d+>> FloatConstant 4 + /// CHECK-DAG: Return [<<Const4>>] + + /// CHECK-START: float Main.FloatSubtraction() constant_folding (after) + /// CHECK-NOT: Sub + + public static float FloatSubtraction() { + float a, b, c; + a = 6F; + b = 2F; + c = a - b; + return c; + } + + /// CHECK-START: double Main.DoubleSubtraction() constant_folding (before) + /// CHECK-DAG: <<Const6:d\d+>> DoubleConstant 6 + /// CHECK-DAG: <<Const2:d\d+>> DoubleConstant 2 + /// CHECK-DAG: <<Sub:d\d+>> Sub [<<Const6>>,<<Const2>>] + /// CHECK-DAG: Return [<<Sub>>] + + /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after) + /// CHECK-DAG: <<Const4:d\d+>> DoubleConstant 4 + /// CHECK-DAG: Return [<<Const4>>] + + /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after) + /// CHECK-NOT: Sub + + public static double DoubleSubtraction() { + double a, b, c; + a = 6D; + b = 2D; + c = a - b; + return c; + } + /** * Exercise constant folding on multiplication. @@ -260,6 +449,48 @@ public class Main { return c; } + /// CHECK-START: float Main.FloatMultiplication() constant_folding (before) + /// CHECK-DAG: <<Const7:f\d+>> FloatConstant 7 + /// CHECK-DAG: <<Const3:f\d+>> FloatConstant 3 + /// CHECK-DAG: <<Mul:f\d+>> Mul [<<Const7>>,<<Const3>>] + /// CHECK-DAG: Return [<<Mul>>] + + /// CHECK-START: float Main.FloatMultiplication() constant_folding (after) + /// CHECK-DAG: <<Const21:f\d+>> FloatConstant 21 + /// CHECK-DAG: Return [<<Const21>>] + + /// CHECK-START: float Main.FloatMultiplication() constant_folding (after) + /// CHECK-NOT: Mul + + public static float FloatMultiplication() { + float a, b, c; + a = 7F; + b = 3F; + c = a * b; + return c; + } + + /// CHECK-START: double Main.DoubleMultiplication() constant_folding (before) + /// CHECK-DAG: <<Const7:d\d+>> DoubleConstant 7 + /// CHECK-DAG: <<Const3:d\d+>> DoubleConstant 3 + /// CHECK-DAG: <<Mul:d\d+>> Mul [<<Const7>>,<<Const3>>] + /// CHECK-DAG: Return [<<Mul>>] + + /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after) + /// CHECK-DAG: <<Const21:d\d+>> DoubleConstant 21 + /// CHECK-DAG: Return [<<Const21>>] + + /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after) + /// CHECK-NOT: Mul + + public static double DoubleMultiplication() { + double a, b, c; + a = 7D; + b = 3D; + c = a * b; + return c; + } + /** * Exercise constant folding on division. @@ -311,6 +542,48 @@ public class Main { return c; } + /// CHECK-START: float Main.FloatDivision() constant_folding (before) + /// CHECK-DAG: <<Const8:f\d+>> FloatConstant 8 + /// CHECK-DAG: <<Const2P5:f\d+>> FloatConstant 2.5 + /// CHECK-DAG: <<Div:f\d+>> Div [<<Const8>>,<<Const2P5>>] + /// CHECK-DAG: Return [<<Div>>] + + /// CHECK-START: float Main.FloatDivision() constant_folding (after) + /// CHECK-DAG: <<Const3P2:f\d+>> FloatConstant 3.2 + /// CHECK-DAG: Return [<<Const3P2>>] + + /// CHECK-START: float Main.FloatDivision() constant_folding (after) + /// CHECK-NOT: Div + + public static float FloatDivision() { + float a, b, c; + a = 8F; + b = 2.5F; + c = a / b; + return c; + } + + /// CHECK-START: double Main.DoubleDivision() constant_folding (before) + /// CHECK-DAG: <<Const8:d\d+>> DoubleConstant 8 + /// CHECK-DAG: <<Const2P5:d\d+>> DoubleConstant 2.5 + /// CHECK-DAG: <<Div:d\d+>> Div [<<Const8>>,<<Const2P5>>] + /// CHECK-DAG: Return [<<Div>>] + + /// CHECK-START: double Main.DoubleDivision() constant_folding (after) + /// CHECK-DAG: <<Const3P2:d\d+>> DoubleConstant 3.2 + /// CHECK-DAG: Return [<<Const3P2>>] + + /// CHECK-START: double Main.DoubleDivision() constant_folding (after) + /// CHECK-NOT: Div + + public static double DoubleDivision() { + double a, b, c; + a = 8D; + b = 2.5D; + c = a / b; + return c; + } + /** * Exercise constant folding on remainder. @@ -362,6 +635,48 @@ public class Main { return c; } + /// CHECK-START: float Main.FloatRemainder() constant_folding (before) + /// CHECK-DAG: <<Const8:f\d+>> FloatConstant 8 + /// CHECK-DAG: <<Const2P5:f\d+>> FloatConstant 2.5 + /// CHECK-DAG: <<Rem:f\d+>> Rem [<<Const8>>,<<Const2P5>>] + /// CHECK-DAG: Return [<<Rem>>] + + /// CHECK-START: float Main.FloatRemainder() constant_folding (after) + /// CHECK-DAG: <<Const0P5:f\d+>> FloatConstant 0.5 + /// CHECK-DAG: Return [<<Const0P5>>] + + /// CHECK-START: float Main.FloatRemainder() constant_folding (after) + /// CHECK-NOT: Rem + + public static float FloatRemainder() { + float a, b, c; + a = 8F; + b = 2.5F; + c = a % b; + return c; + } + + /// CHECK-START: double Main.DoubleRemainder() constant_folding (before) + /// CHECK-DAG: <<Const8:d\d+>> DoubleConstant 8 + /// CHECK-DAG: <<Const2P5:d\d+>> DoubleConstant 2.5 + /// CHECK-DAG: <<Rem:d\d+>> Rem [<<Const8>>,<<Const2P5>>] + /// CHECK-DAG: Return [<<Rem>>] + + /// CHECK-START: double Main.DoubleRemainder() constant_folding (after) + /// CHECK-DAG: <<Const0P5:d\d+>> DoubleConstant 0.5 + /// CHECK-DAG: Return [<<Const0P5>>] + + /// CHECK-START: double Main.DoubleRemainder() constant_folding (after) + /// CHECK-NOT: Rem + + public static double DoubleRemainder() { + double a, b, c; + a = 8D; + b = 2.5D; + c = a % b; + return c; + } + /** * Exercise constant folding on left shift. @@ -1197,25 +1512,37 @@ public class Main { } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { assertIntEquals(-42, IntNegation()); assertLongEquals(-42L, LongNegation()); + assertFloatEquals(-42F, FloatNegation()); + assertDoubleEquals(-42D, DoubleNegation()); assertIntEquals(3, IntAddition1()); assertIntEquals(14, IntAddition2()); assertLongEquals(3L, LongAddition()); + assertFloatEquals(3F, FloatAddition()); + assertDoubleEquals(3D, DoubleAddition()); assertIntEquals(4, IntSubtraction()); assertLongEquals(4L, LongSubtraction()); + assertFloatEquals(4F, FloatSubtraction()); + assertDoubleEquals(4D, DoubleSubtraction()); assertIntEquals(21, IntMultiplication()); assertLongEquals(21L, LongMultiplication()); + assertFloatEquals(21F, FloatMultiplication()); + assertDoubleEquals(21D, DoubleMultiplication()); assertIntEquals(2, IntDivision()); assertLongEquals(2L, LongDivision()); + assertFloatEquals(3.2F, FloatDivision()); + assertDoubleEquals(3.2D, DoubleDivision()); assertIntEquals(2, IntRemainder()); assertLongEquals(2L, LongRemainder()); + assertFloatEquals(0.5F, FloatRemainder()); + assertDoubleEquals(0.5D, DoubleRemainder()); assertIntEquals(4, ShlIntLong()); assertLongEquals(12L, ShlLongInt()); @@ -1259,6 +1586,24 @@ public class Main { assertFalse(CmpFloatGreaterThanNaN(arbitrary)); assertFalse(CmpDoubleLessThanNaN(arbitrary)); + Main main = new Main(); + assertIntEquals(1, main.smaliCmpLongConstants()); + assertIntEquals(-1, main.smaliCmpGtFloatConstants()); + assertIntEquals(-1, main.smaliCmpLtFloatConstants()); + assertIntEquals(-1, main.smaliCmpGtDoubleConstants()); + assertIntEquals(-1, main.smaliCmpLtDoubleConstants()); + + assertIntEquals(0, main.smaliCmpLongSameConstant()); + assertIntEquals(0, main.smaliCmpGtFloatSameConstant()); + assertIntEquals(0, main.smaliCmpLtFloatSameConstant()); + assertIntEquals(0, main.smaliCmpGtDoubleSameConstant()); + assertIntEquals(0, main.smaliCmpLtDoubleSameConstant()); + + assertIntEquals(1, main.smaliCmpGtFloatConstantWithNaN()); + assertIntEquals(-1, main.smaliCmpLtFloatConstantWithNaN()); + assertIntEquals(1, main.smaliCmpGtDoubleConstantWithNaN()); + assertIntEquals(-1, main.smaliCmpLtDoubleConstantWithNaN()); + assertIntEquals(33, ReturnInt33()); assertIntEquals(2147483647, ReturnIntMax()); assertIntEquals(0, ReturnInt0()); @@ -1275,4 +1620,10 @@ public class Main { assertDoubleEquals(34, ReturnDouble34()); assertDoubleEquals(99.25, ReturnDouble99P25()); } + + Main() throws ClassNotFoundException { + testCmp = Class.forName("TestCmp"); + } + + private Class<?> testCmp; } diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java index 31bb94cb8c..32bbc5b61d 100644 --- a/test/449-checker-bce/src/Main.java +++ b/test/449-checker-bce/src/Main.java @@ -391,6 +391,36 @@ public class Main { array[base + 1] = 1; } + /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (before) + /// CHECK: BoundsCheck + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArraySet + /// CHECK: BoundsCheck + /// CHECK: ArraySet + + /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (after) + /// CHECK: Deoptimize + /// CHECK: Deoptimize + /// CHECK-NOT: BoundsCheck + /// CHECK: ArraySet + /// CHECK-NOT: BoundsCheck + /// CHECK: ArraySet + /// CHECK-NOT: BoundsCheck + /// CHECK: ArraySet + /// CHECK-NOT: BoundsCheck + /// CHECK: ArraySet + + static void constantIndexing10(int[] array, int base) { + // Offset hidden in incremented base. + array[base] = 1; + array[++base] = 2; + array[++base] = 3; + array[++base] = 4; + } + static void runAllConstantIndices() { int[] a1 = { 0 }; int[] a6 = { 0, 0, 0, 0, 0, 0 }; @@ -502,6 +532,12 @@ public class Main { a6[3] != 3 || a6[4] != 40 || a6[5] != 10) { System.out.println("constant indices 9 failed!"); } + + constantIndexing10(a6, 0); + if (a6[0] != 1 || a6[1] != 2 || a6[2] != 3 || + a6[3] != 4 || a6[4] != 40 || a6[5] != 10) { + System.out.println("constant indices 10 failed!"); + } } // A helper into which the actual throwing function should be inlined. diff --git a/test/529-checker-unresolved/build b/test/529-checker-unresolved/build index 8c3c4f8952..d85035b669 100644 --- a/test/529-checker-unresolved/build +++ b/test/529-checker-unresolved/build @@ -29,14 +29,12 @@ mv classes/UnresolvedInterface.class classes-ex mv classes/UnresolvedSuperClass.class classes-ex if [ ${USE_JACK} = "true" ]; then - # Create .jack files from classes generated with javac. - ${JILL} classes --output classes.jack - ${JILL} classes-ex --output classes-ex.jack + jar cf classes.jill.jar -C classes . + jar cf classes-ex.jill.jar -C classes-ex . - # Create DEX files from .jack files. - ${JACK} --import classes.jack --output-dex . + ${JACK} --import classes.jill.jar --output-dex . zip $TEST_NAME.jar classes.dex - ${JACK} --import classes-ex.jack --output-dex . + ${JACK} --import classes-ex.jill.jar --output-dex . zip ${TEST_NAME}-ex.jar classes.dex else if [ ${NEED_DEX} = "true" ]; then diff --git a/test/566-checker-codegen-select/src/Main.java b/test/566-checker-codegen-select/src/Main.java index 3a1b3fcf85..e215ab0309 100644 --- a/test/566-checker-codegen-select/src/Main.java +++ b/test/566-checker-codegen-select/src/Main.java @@ -20,13 +20,6 @@ public class Main { /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{j\d+}},{{j\d+}}] /// CHECK-NEXT: Select [{{j\d+}},{{j\d+}},<<Cond>>] - // Condition must be materialized on X86 because it would need too many - // registers otherwise. - /// CHECK-START-X86: long Main.$noinline$longSelect(long) disassembly (after) - /// CHECK: LessThanOrEqual - /// CHECK-NEXT: cmp - /// CHECK: Select - public long $noinline$longSelect(long param) { if (doThrow) { throw new Error(); } long val_true = longB; diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc index 4c58b39319..09e97ea751 100644 --- a/test/570-checker-osr/osr.cc +++ b/test/570-checker-osr/osr.cc @@ -41,7 +41,8 @@ class OsrVisitor : public StackVisitor { (m_name.compare("$noinline$returnDouble") == 0) || (m_name.compare("$noinline$returnLong") == 0) || (m_name.compare("$noinline$deopt") == 0) || - (m_name.compare("$noinline$inlineCache") == 0)) { + (m_name.compare("$noinline$inlineCache") == 0) || + (m_name.compare("$noinline$stackOverflow") == 0)) { const OatQuickMethodHeader* header = Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m); if (header != nullptr && header == GetCurrentOatQuickMethodHeader()) { @@ -91,7 +92,8 @@ class ProfilingInfoVisitor : public StackVisitor { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); - if (m_name.compare("$noinline$inlineCache") == 0) { + if ((m_name.compare("$noinline$inlineCache") == 0) || + (m_name.compare("$noinline$stackOverflow") == 0)) { ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true); return false; } @@ -119,7 +121,8 @@ class OsrCheckVisitor : public StackVisitor { std::string m_name(m->GetName()); jit::Jit* jit = Runtime::Current()->GetJit(); - if (m_name.compare("$noinline$inlineCache") == 0 && jit != nullptr) { + if ((m_name.compare("$noinline$inlineCache") == 0) || + (m_name.compare("$noinline$stackOverflow") == 0)) { while (jit->GetCodeCache()->LookupOsrMethodHeader(m) == nullptr) { // Sleep to yield to the compiler thread. sleep(0); diff --git a/test/570-checker-osr/run b/test/570-checker-osr/run new file mode 100755 index 0000000000..24d69b4b3b --- /dev/null +++ b/test/570-checker-osr/run @@ -0,0 +1,18 @@ +#!/bin/bash +# +# 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. + +# Ensure this test is not subject to code collection. +exec ${RUN} "$@" --runtime-option -Xjitinitialsize:32M diff --git a/test/570-checker-osr/src/Main.java b/test/570-checker-osr/src/Main.java index 828908a582..1142d49eed 100644 --- a/test/570-checker-osr/src/Main.java +++ b/test/570-checker-osr/src/Main.java @@ -40,6 +40,9 @@ public class Main { if ($noinline$inlineCache(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) { throw new Error("Unexpected return value"); } + + $noinline$stackOverflow(new Main(), /* isSecondInvocation */ false); + $noinline$stackOverflow(new SubMain(), /* isSecondInvocation */ true); } public static int $noinline$returnInt() { @@ -129,7 +132,32 @@ public class Main { return Main.class; } - public static int[] array = new int[4]; + public void otherInlineCache() { + return; + } + + public static void $noinline$stackOverflow(Main m, boolean isSecondInvocation) { + // If we are running in non-JIT mode, or were unlucky enough to get this method + // already JITted, just return the expected value. + if (!ensureInInterpreter()) { + return; + } + + // We need a ProfilingInfo object to populate the 'otherInlineCache' call. + ensureHasProfilingInfo(); + + if (isSecondInvocation) { + // Ensure we have an OSR code and we jump to it. + while (!ensureInOsrCode()) {} + } + + for (int i = 0; i < (isSecondInvocation ? 10000000 : 1); ++i) { + // The first invocation of $noinline$stackOverflow will populate the inline + // cache with Main. The second invocation of the method, will see a SubMain + // and will therefore trigger deoptimization. + m.otherInlineCache(); + } + } public static native boolean ensureInInterpreter(); public static native boolean ensureInOsrCode(); @@ -147,4 +175,8 @@ class SubMain extends Main { public Main inlineCache() { return new SubMain(); } + + public void otherInlineCache() { + return; + } } diff --git a/test/570-checker-select/src/Main.java b/test/570-checker-select/src/Main.java index 8a4cf603af..59741d6d05 100644 --- a/test/570-checker-select/src/Main.java +++ b/test/570-checker-select/src/Main.java @@ -29,6 +29,11 @@ public class Main { /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] /// CHECK: cmovnz/ne + /// CHECK-START-X86: int Main.BoolCond_IntVarVar(boolean, int, int) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + public static int BoolCond_IntVarVar(boolean cond, int x, int y) { return cond ? x : y; } @@ -46,6 +51,11 @@ public class Main { /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] /// CHECK: cmovnz/ne + /// CHECK-START-X86: int Main.BoolCond_IntVarCst(boolean, int) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + public static int BoolCond_IntVarCst(boolean cond, int x) { return cond ? x : 1; } @@ -63,6 +73,11 @@ public class Main { /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] /// CHECK: cmovnz/ne + /// CHECK-START-X86: int Main.BoolCond_IntCstVar(boolean, int) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + public static int BoolCond_IntCstVar(boolean cond, int y) { return cond ? 1 : y; } @@ -80,6 +95,12 @@ public class Main { /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] /// CHECK: cmovnz/neq + /// CHECK-START-X86: long Main.BoolCond_LongVarVar(boolean, long, long) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + /// CHECK-NEXT: cmovnz/ne + public static long BoolCond_LongVarVar(boolean cond, long x, long y) { return cond ? x : y; } @@ -97,6 +118,12 @@ public class Main { /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] /// CHECK: cmovnz/neq + /// CHECK-START-X86: long Main.BoolCond_LongVarCst(boolean, long) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + /// CHECK-NEXT: cmovnz/ne + public static long BoolCond_LongVarCst(boolean cond, long x) { return cond ? x : 1L; } @@ -114,6 +141,12 @@ public class Main { /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] /// CHECK: cmovnz/neq + /// CHECK-START-X86: long Main.BoolCond_LongCstVar(boolean, long) disassembly (after) + /// CHECK: <<Cond:z\d+>> ParameterValue + /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + /// CHECK-NEXT: cmovnz/ne + public static long BoolCond_LongCstVar(boolean cond, long y) { return cond ? 1L : y; } @@ -168,6 +201,11 @@ public class Main { /// CHECK-NEXT: Select [{{i\d+}},{{i\d+}},<<Cond>>] /// CHECK: cmovle/ng + /// CHECK-START-X86: int Main.IntNonmatCond_IntVarVar(int, int, int, int) disassembly (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK-NEXT: Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK: cmovle/ng + public static int IntNonmatCond_IntVarVar(int a, int b, int x, int y) { return a > b ? x : y; } @@ -189,6 +227,11 @@ public class Main { /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] /// CHECK: cmovle/ng + /// CHECK-START-X86: int Main.IntMatCond_IntVarVar(int, int, int, int) disassembly (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK: cmovle/ng + public static int IntMatCond_IntVarVar(int a, int b, int x, int y) { int result = (a > b ? x : y); return result + (a > b ? 0 : 1); @@ -208,6 +251,12 @@ public class Main { /// CHECK-NEXT: Select [{{j\d+}},{{j\d+}},<<Cond>>] /// CHECK: cmovle/ngq + /// CHECK-START-X86: long Main.IntNonmatCond_LongVarVar(int, int, long, long) disassembly (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK-NEXT: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK: cmovle/ng + /// CHECK-NEXT: cmovle/ng + public static long IntNonmatCond_LongVarVar(int a, int b, long x, long y) { return a > b ? x : y; } @@ -232,6 +281,15 @@ public class Main { /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] /// CHECK: cmovnz/neq + /// CHECK-START-X86: long Main.IntMatCond_LongVarVar(int, int, long, long) disassembly (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK-NEXT: cmovle/ng + /// CHECK-NEXT: cmovle/ng + /// CHECK: Select [{{j\d+}},{{j\d+}},<<Cond>>] + /// CHECK: cmovnz/ne + /// CHECK-NEXT: cmovnz/ne + public static long IntMatCond_LongVarVar(int a, int b, long x, long y) { long result = (a > b ? x : y); return result + (a > b ? 0L : 1L); diff --git a/test/574-irreducible-and-constant-area/expected.txt b/test/574-irreducible-and-constant-area/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/574-irreducible-and-constant-area/expected.txt diff --git a/test/574-irreducible-and-constant-area/info.txt b/test/574-irreducible-and-constant-area/info.txt new file mode 100644 index 0000000000..e957a5ae6b --- /dev/null +++ b/test/574-irreducible-and-constant-area/info.txt @@ -0,0 +1,3 @@ +Regression test for intrinsics on x86, which used to wrongly assume +a HInvokeStaticOrDirect must have a special input (does not apply for irreducible +loops). diff --git a/test/574-irreducible-and-constant-area/run b/test/574-irreducible-and-constant-area/run new file mode 100755 index 0000000000..ffdbcc9cf2 --- /dev/null +++ b/test/574-irreducible-and-constant-area/run @@ -0,0 +1,18 @@ +#!/bin/bash +# +# 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. + +# Don't do relocation, as this affects this test. +exec ${RUN} "$@" --no-relocate diff --git a/test/574-irreducible-and-constant-area/smali/IrreducibleLoop.smali b/test/574-irreducible-and-constant-area/smali/IrreducibleLoop.smali new file mode 100644 index 0000000000..d7d43466d1 --- /dev/null +++ b/test/574-irreducible-and-constant-area/smali/IrreducibleLoop.smali @@ -0,0 +1,35 @@ +# 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. + +.class public LIrreducibleLoop; + +.super Ljava/lang/Object; + +.method public static simpleLoop(I)I + .registers 5 + const/16 v0, 42 + const/16 v1, 42 + const-wide/high16 v2, 0x4000000000000000L + if-eq p0, v0, :other_loop_entry + :loop_entry + invoke-static {v1, v1}, LMain;->$inline$foo(FF)V + invoke-static {v2, v3, v2, v3}, LMain;->$inline$foo(DD)V + if-ne p0, v0, :exit + add-int v0, v0, v0 + :other_loop_entry + add-int v0, v0, v0 + goto :loop_entry + :exit + return v0 +.end method diff --git a/test/574-irreducible-and-constant-area/src/Main.java b/test/574-irreducible-and-constant-area/src/Main.java new file mode 100644 index 0000000000..3cdd92456c --- /dev/null +++ b/test/574-irreducible-and-constant-area/src/Main.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import java.lang.reflect.Method; + +public class Main { + // Workaround for b/18051191. + class InnerClass {} + + public static void main(String[] args) throws Exception { + Class<?> c = Class.forName("IrreducibleLoop"); + Method m = c.getMethod("simpleLoop", int.class); + Object[] arguments = { 42 }; + m.invoke(null, arguments); + } + + public static void $inline$foo(float a, float b) { + Math.abs(a); + Math.max(a, b); + Math.min(a, b); + } + + public static void $inline$foo(double a, double b) { + Math.abs(a); + Math.max(a, b); + Math.min(a, b); + } +} diff --git a/test/575-checker-isnan/expected.txt b/test/575-checker-isnan/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/575-checker-isnan/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/575-checker-isnan/info.txt b/test/575-checker-isnan/info.txt new file mode 100644 index 0000000000..5c48a6a877 --- /dev/null +++ b/test/575-checker-isnan/info.txt @@ -0,0 +1 @@ +Unit test for float/double isNaN() operation. diff --git a/test/575-checker-isnan/src/Main.java b/test/575-checker-isnan/src/Main.java new file mode 100644 index 0000000000..cc71e5e27d --- /dev/null +++ b/test/575-checker-isnan/src/Main.java @@ -0,0 +1,126 @@ +/* + * 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. + */ + +public class Main { + + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (before) + /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after) + /// CHECK-DAG: <<Result:z\d+>> NotEqual + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + private static boolean isNaN32(float x) { + return Float.isNaN(x); + } + + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (before) + /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after) + /// CHECK-DAG: <<Result:z\d+>> NotEqual + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + private static boolean isNaN64(double x) { + return Double.isNaN(x); + } + + public static void main(String args[]) { + // A few distinct numbers. + expectFalse(isNaN32(Float.NEGATIVE_INFINITY)); + expectFalse(isNaN32(-1.0f)); + expectFalse(isNaN32(-0.0f)); + expectFalse(isNaN32(0.0f)); + expectFalse(isNaN32(1.0f)); + expectFalse(isNaN32(Float.POSITIVE_INFINITY)); + + // A few distinct subnormal numbers. + expectFalse(isNaN32(Float.intBitsToFloat(0x00400000))); + expectFalse(isNaN32(Float.intBitsToFloat(0x80400000))); + expectFalse(isNaN32(Float.intBitsToFloat(0x00000001))); + expectFalse(isNaN32(Float.intBitsToFloat(0x80000001))); + + // A few NaN numbers. + expectTrue(isNaN32(Float.NaN)); + expectTrue(isNaN32(0.0f / 0.0f)); + expectTrue(isNaN32((float)Math.sqrt(-1.0f))); + float[] fvals = { + Float.intBitsToFloat(0x7f800001), + Float.intBitsToFloat(0x7fa00000), + Float.intBitsToFloat(0x7fc00000), + Float.intBitsToFloat(0x7fffffff), + Float.intBitsToFloat(0xff800001), + Float.intBitsToFloat(0xffa00000), + Float.intBitsToFloat(0xffc00000), + Float.intBitsToFloat(0xffffffff) + }; + for (int i = 0; i < fvals.length; i++) { + expectTrue(isNaN32(fvals[i])); + } + + // A few distinct numbers. + expectFalse(isNaN64(Double.NEGATIVE_INFINITY)); + expectFalse(isNaN32(-1.0f)); + expectFalse(isNaN64(-0.0d)); + expectFalse(isNaN64(0.0d)); + expectFalse(isNaN64(1.0d)); + expectFalse(isNaN64(Double.POSITIVE_INFINITY)); + + // A few distinct subnormal numbers. + expectFalse(isNaN64(Double.longBitsToDouble(0x0008000000000000l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x8008000000000000l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x0000000000000001l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x8000000000000001l))); + + // A few NaN numbers. + expectTrue(isNaN64(Double.NaN)); + expectTrue(isNaN64(0.0d / 0.0d)); + expectTrue(isNaN64(Math.sqrt(-1.0d))); + double[] dvals = { + Double.longBitsToDouble(0x7ff0000000000001L), + Double.longBitsToDouble(0x7ff4000000000000L), + Double.longBitsToDouble(0x7ff8000000000000L), + Double.longBitsToDouble(0x7fffffffffffffffL), + Double.longBitsToDouble(0xfff0000000000001L), + Double.longBitsToDouble(0xfff4000000000000L), + Double.longBitsToDouble(0xfff8000000000000L), + Double.longBitsToDouble(0xffffffffffffffffL) + }; + for (int i = 0; i < dvals.length; i++) { + expectTrue(isNaN64(dvals[i])); + } + + System.out.println("passed"); + } + + private static void expectTrue(boolean value) { + if (!value) { + throw new Error("Expected True"); + } + } + + private static void expectFalse(boolean value) { + if (value) { + throw new Error("Expected False"); + } + } +} diff --git a/test/575-checker-string-init-alias/expected.txt b/test/575-checker-string-init-alias/expected.txt new file mode 100644 index 0000000000..6a5618ebc6 --- /dev/null +++ b/test/575-checker-string-init-alias/expected.txt @@ -0,0 +1 @@ +JNI_OnLoad called diff --git a/test/575-checker-string-init-alias/info.txt b/test/575-checker-string-init-alias/info.txt new file mode 100644 index 0000000000..a91ea645e7 --- /dev/null +++ b/test/575-checker-string-init-alias/info.txt @@ -0,0 +1,2 @@ +Test for the String.<init> change and deoptimization: make +sure the compiler knows how to handle dex aliases. diff --git a/test/575-checker-string-init-alias/smali/TestCase.smali b/test/575-checker-string-init-alias/smali/TestCase.smali new file mode 100644 index 0000000000..ff04b278a4 --- /dev/null +++ b/test/575-checker-string-init-alias/smali/TestCase.smali @@ -0,0 +1,72 @@ +# 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. + +.class public LTestCase; + +.super Ljava/lang/Object; + +.field public static staticField:Ljava/lang/String; + +## CHECK-START: void TestCase.testNoAlias(int[], java.lang.String) register (after) +## CHECK: <<Null:l\d+>> NullConstant +## CHECK: Deoptimize env:[[<<Null>>,{{.*]]}} +## CHECK: InvokeStaticOrDirect method_name:java.lang.String.<init> +.method public static testNoAlias([ILjava/lang/String;)V + .registers 6 + const v1, 0 + const v2, 1 + new-instance v0, Ljava/lang/String; + + # Will deoptimize. + aget v3, p0, v1 + + # Check that we're being executed by the interpreter. + invoke-static {}, LMain;->assertIsInterpreted()V + + invoke-direct {v0, p1}, Ljava/lang/String;-><init>(Ljava/lang/String;)V + + sput-object v0, LTestCase;->staticField:Ljava/lang/String; + + # Will throw AIOOBE. + aget v3, p0, v2 + + return-void +.end method + +## CHECK-START: void TestCase.testAlias(int[], java.lang.String) register (after) +## CHECK: <<New:l\d+>> NewInstance +## CHECK: Deoptimize env:[[<<New>>,<<New>>,{{.*]]}} +## CHECK: InvokeStaticOrDirect method_name:java.lang.String.<init> +.method public static testAlias([ILjava/lang/String;)V + .registers 7 + const v2, 0 + const v3, 1 + new-instance v0, Ljava/lang/String; + move-object v1, v0 + + # Will deoptimize. + aget v4, p0, v2 + + # Check that we're being executed by the interpreter. + invoke-static {}, LMain;->assertIsInterpreted()V + + invoke-direct {v1, p1}, Ljava/lang/String;-><init>(Ljava/lang/String;)V + + sput-object v1, LTestCase;->staticField:Ljava/lang/String; + + # Will throw AIOOBE. + aget v4, p0, v3 + + return-void +.end method diff --git a/test/575-checker-string-init-alias/src/Main.java b/test/575-checker-string-init-alias/src/Main.java new file mode 100644 index 0000000000..1ab320748a --- /dev/null +++ b/test/575-checker-string-init-alias/src/Main.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +public class Main { + // Workaround for b/18051191. + class Inner {} + + public static native void assertIsInterpreted(); + + private static void assertEqual(String expected, String actual) { + if (!expected.equals(actual)) { + throw new Error("Assertion failed: " + expected + " != " + actual); + } + } + + public static void main(String[] args) throws Throwable { + System.loadLibrary(args[0]); + Class<?> c = Class.forName("TestCase"); + int[] array = new int[1]; + + { + Method m = c.getMethod("testNoAlias", int[].class, String.class); + try { + m.invoke(null, new Object[] { array , "foo" }); + throw new Error("Expected AIOOBE"); + } catch (InvocationTargetException e) { + if (!(e.getCause() instanceof ArrayIndexOutOfBoundsException)) { + throw new Error("Expected AIOOBE"); + } + // Ignore + } + Field field = c.getField("staticField"); + assertEqual("foo", (String)field.get(null)); + } + + { + Method m = c.getMethod("testAlias", int[].class, String.class); + try { + m.invoke(null, new Object[] { array, "bar" }); + throw new Error("Expected AIOOBE"); + } catch (InvocationTargetException e) { + if (!(e.getCause() instanceof ArrayIndexOutOfBoundsException)) { + throw new Error("Expected AIOOBE"); + } + // Ignore + } + Field field = c.getField("staticField"); + assertEqual("bar", (String)field.get(null)); + } + } +} diff --git a/test/576-polymorphic-inlining/expected.txt b/test/576-polymorphic-inlining/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/576-polymorphic-inlining/expected.txt diff --git a/test/576-polymorphic-inlining/info.txt b/test/576-polymorphic-inlining/info.txt new file mode 100644 index 0000000000..b3ef0c8fba --- /dev/null +++ b/test/576-polymorphic-inlining/info.txt @@ -0,0 +1 @@ +Test for polymorphic inlining. diff --git a/test/576-polymorphic-inlining/src/Main.java b/test/576-polymorphic-inlining/src/Main.java new file mode 100644 index 0000000000..d8d09aff87 --- /dev/null +++ b/test/576-polymorphic-inlining/src/Main.java @@ -0,0 +1,103 @@ +/* + * 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. + */ + +public class Main { + public static void main(String[] args) { + for (int i = 0; i < 20000; ++i) { + $noinline$testVoid(new Main()); + $noinline$testVoid(new SubMain()); + $noinline$testVoid(new SubSubMain()); + + $noinline$testWithReturnValue(new Main()); + $noinline$testWithReturnValue(new SubMain()); + $noinline$testWithReturnValue(new SubSubMain()); + + $noinline$testWithBackEdge(new Main()); + $noinline$testWithBackEdge(new SubMain()); + $noinline$testWithBackEdge(new SubSubMain()); + } + } + + public static void assertIdentical(Object expected, Object actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void $noinline$testVoid(Main m) { + if (doThrow) throw new Error(""); + m.willInlineVoid(); + m.willOnlyInlineForMainVoid(); + } + + public static void $noinline$testWithReturnValue(Main m) { + if (doThrow) throw new Error(""); + assertIdentical(m.getClass(), m.willInlineWithReturnValue()); + assertIdentical(m.getClass(), m.willOnlyInlineForMainWithReturnValue()); + } + + public static void $noinline$testWithBackEdge(Main m) { + if (doThrow) throw new Error(""); + for (int i = 0; i < 10; ++i) { + m.willInlineVoid(); + } + for (int i = 0; i < 10; ++i) { + m.willOnlyInlineForMainVoid(); + } + } + + public void willInlineVoid() { + } + + public void willOnlyInlineForMainVoid() { + } + + public Class willInlineWithReturnValue() { + return Main.class; + } + + public Class willOnlyInlineForMainWithReturnValue() { + return Main.class; + } + public static boolean doThrow; +} + +class SubMain extends Main { + public void willOnlyInlineForMainVoid() { + if (doThrow) throw new Error(""); + } + + public void willInlineVoid() { + } + + public Class willInlineWithReturnValue() { + return SubMain.class; + } + + public Class willOnlyInlineForMainWithReturnValue() { + return SubMain.class; + } +} + +class SubSubMain extends SubMain { + public Class willInlineWithReturnValue() { + return SubSubMain.class; + } + + public Class willOnlyInlineForMainWithReturnValue() { + return SubSubMain.class; + } +} diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index b3560b634b..364be59919 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -42,8 +42,7 @@ TEST_ART_RUN_TEST_ORDERONLY_DEPENDENCIES := ifeq ($(ANDROID_COMPILE_WITH_JACK),true) TEST_ART_RUN_TEST_DEPENDENCIES += \ - $(JACK) \ - $(JILL_JAR) + $(JACK) TEST_ART_RUN_TEST_ORDERONLY_DEPENDENCIES += setup-jack-server endif @@ -72,8 +71,8 @@ $$(dmart_target): $(TEST_ART_RUN_TEST_DEPENDENCIES) $(TARGET_JACK_CLASSPATH_DEPE DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \ JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK=$(abspath $(JACK)) \ + JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK_CLASSPATH=$(TARGET_JACK_CLASSPATH) \ - JILL_JAR=$(abspath $(JILL_JAR)) \ $(LOCAL_PATH)/run-test $$(PRIVATE_RUN_TEST_OPTIONS) --output-path $$(abspath $$(dir $$@)) $(1) $(hide) touch $$@ @@ -962,8 +961,8 @@ $$(run_test_rule_name): $(TEST_ART_RUN_TEST_DEPENDENCIES) $(HOST_OUT_EXECUTABLES DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \ JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK=$(abspath $(JACK)) \ + JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK_CLASSPATH=$$(PRIVATE_JACK_CLASSPATH) \ - JILL_JAR=$(abspath $(JILL_JAR)) \ art/test/run-test $$(PRIVATE_RUN_TEST_OPTIONS) $(12) \ && $$(call ART_TEST_PASSED,$$@) || $$(call ART_TEST_FAILED,$$@) $$(hide) (echo $(MAKECMDGOALS) | grep -q $$@ && \ diff --git a/test/run-test b/test/run-test index faa597e1ca..f1875d71a5 100755 --- a/test/run-test +++ b/test/run-test @@ -88,13 +88,7 @@ if [ -z "$JACK_CLASSPATH" ]; then export JACK_CLASSPATH="${OUT_DIR:-$ANDROID_BUILD_TOP/out}/host/common/obj/JAVA_LIBRARIES/core-libart-hostdex_intermediates/classes.jack:${OUT_DIR:-$ANDROID_BUILD_TOP/out}/host/common/obj/JAVA_LIBRARIES/core-oj-hostdex_intermediates/classes.jack" fi -# If JILL_JAR is not set, assume it is located in the prebuilts directory. -if [ -z "$JILL_JAR" ]; then - export JILL_JAR="$ANDROID_BUILD_TOP/prebuilts/sdk/tools/jill.jar" -fi - export JACK="$JACK -g -cp $JACK_CLASSPATH" -export JILL="java -jar $JILL_JAR" info="info.txt" build="build" |