diff options
Diffstat (limited to 'test')
63 files changed, 1376 insertions, 793 deletions
diff --git a/test/048-reflect-v8/expected.txt b/test/048-reflect-v8/expected.txt index 3109eccda6..2d0b4ccb6b 100644 --- a/test/048-reflect-v8/expected.txt +++ b/test/048-reflect-v8/expected.txt @@ -1,95 +1,4 @@ -============================== -Are These Methods Default: -============================== -IsDefaultTest$DefaultInterface is default = yes -IsDefaultTest$RegularInterface is default = no -IsDefaultTest$ImplementsWithDefault is default = yes -IsDefaultTest$ImplementsWithRegular is default = no -============================== -Class annotations by type: -============================== -Annotations by type, defined by class SingleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Annotations by type, defined by class SingleUser with annotation Calendars: <empty> -Annotations by type, defined by class User with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) -Annotations by type, defined by class User with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Annotations by type, defined by class User2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) -Annotations by type, defined by class User2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) -Annotations by type, defined by class UserComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) -Annotations by type, defined by class UserComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) -Annotations by type, defined by class UserSub with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) -Annotations by type, defined by class UserSub with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Annotations by type, defined by class UserSub2 with annotation Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) -Annotations by type, defined by class UserSub2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) ------------------------------ ------------------------------ -============================== -Class declared annotation: -============================== -Declared annotations by class class SingleUser, annotation interface Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Declared annotations by class class SingleUser, annotation interface Calendars: <null> -Declared annotations by class class User, annotation interface Calendar: <null> -Declared annotations by class class User, annotation interface Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Declared annotations by class class UserComplex, annotation interface Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6) -Declared annotations by class class UserComplex, annotation interface Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) -Declared annotations by class class UserSub, annotation interface Calendar: <null> -Declared annotations by class class UserSub, annotation interface Calendars: <null> -Declared annotations by class class UserSub2, annotation interface Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) -Declared annotations by class class UserSub2, annotation interface Calendars: <null> ------------------------------ ------------------------------ -============================== -Declared class annotations by type: -============================== -Declared annnotations by type, defined by class SingleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Declared annnotations by type, defined by class SingleUser with annotation Calendars: <empty> -Declared annnotations by type, defined by class User with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) -Declared annnotations by type, defined by class User with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Declared annnotations by type, defined by class User2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) -Declared annnotations by type, defined by class User2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) -Declared annnotations by type, defined by class UserComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) -Declared annnotations by type, defined by class UserComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) -Declared annnotations by type, defined by class UserSub with annotation Calendar: <empty> -Declared annnotations by type, defined by class UserSub with annotation Calendars: <empty> -Declared annnotations by type, defined by class UserSub2 with annotation Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) -Declared annnotations by type, defined by class UserSub2 with annotation Calendars: <empty> ------------------------------ ------------------------------ -============================== -Method annotations by type: -============================== -Annotations by type, defined by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Annotations by type, defined by method singleUser with annotation Calendars: <empty> -Annotations by type, defined by method user with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) -Annotations by type, defined by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Annotations by type, defined by method user2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) -Annotations by type, defined by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) -Annotations by type, defined by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) -Annotations by type, defined by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) ------------------------------ ------------------------------ -============================== -Declared method annotations: -============================== -Annotations declared by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Annotations declared by method singleUser with annotation Calendars: <null> -Annotations declared by method user with annotation Calendar: <null> -Annotations declared by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Annotations declared by method user2 with annotation Calendar: <null> -Annotations declared by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) -Annotations declared by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6) -Annotations declared by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) ------------------------------ ------------------------------ -============================== -Declared method annotations by type: -============================== -Annotations by type, defined by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) -Annotations by type, defined by method singleUser with annotation Calendars: <empty> -Annotations by type, defined by method user with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) -Annotations by type, defined by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) -Annotations by type, defined by method user2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) -Annotations by type, defined by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) -Annotations by type, defined by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) -Annotations by type, defined by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) ------------------------------ ------------------------------ +Main$DefaultInterface is default = yes +Main$RegularInterface is default = no +Main$ImplementsWithDefault is default = yes +Main$ImplementsWithRegular is default = no diff --git a/test/048-reflect-v8/src/AnnotationTest.java b/test/048-reflect-v8/src/AnnotationTest.java deleted file mode 100644 index 75e684557c..0000000000 --- a/test/048-reflect-v8/src/AnnotationTest.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 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.annotation.Annotation; -import java.lang.reflect.Method; - -public class AnnotationTest extends AnnotationTestHelpers { - public static void testAnnotationsByType() { - System.out.println("=============================="); - System.out.println("Class annotations by type:"); - System.out.println("=============================="); - - // Print associated annotations: - // * A is directly present or repeatably present on an element E; - // * No annotation of A is directly/repeatably present on an element - // AND E is a class AND A's type is inheritable, AND A is associated with its superclass. - // (Looks through subtypes recursively only if there's 0 result at each level, - // and the annotation is @Inheritable). - printAnnotationsByType(Calendar.class, SingleUser.class); - printAnnotationsByType(Calendars.class, SingleUser.class); - - printAnnotationsByType(Calendar.class, User.class); - printAnnotationsByType(Calendars.class, User.class); - - printAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y' - printAnnotationsByType(Calendars.class, User2.class); - - // NOTE: - // Order of outer-most annotations Calendars[C,C],S vs C,Calendars[C,C] is unspecified. - // In particular it's the order of #getDeclaredAnnotations which is completely unmentioned. - // The only requirement for #getAnnotationsByType is to have same ordering as - // #getDeclaredAnnotations. - // (Calendars[] itself has to maintain value() order). - printAnnotationsByType(Calendar.class, UserComplex.class); // Cs(C,C),C collapses into C,C,C. - printAnnotationsByType(Calendars.class, UserComplex.class); - - printAnnotationsByType(Calendar.class, UserSub.class); - printAnnotationsByType(Calendars.class, UserSub.class); - - printAnnotationsByType(Calendar.class, UserSub2.class); - // The directly present "Calendar" annotation masks all the repeatably present - // "Calendar" annotations coming from User. - printAnnotationsByType(Calendars.class, UserSub2.class); - // Edge case: UserSub2 doesn't directly have a Calendars annotation, - // so it doesn't mask the "User" Calendars annotation. - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - - } - - public static void testDeclaredAnnotation() { - System.out.println("=============================="); - System.out.println("Class declared annotation:"); - System.out.println("=============================="); - - // Print directly present annotations: - // - // The element E has an annotation_item for it (accessible through an - // annotations_directory_item) corresponding to an annotation A, - // and A's type_idx must match that on the encoded_annotation (from the annotation_item). - // (Does not look through the subtypes recursively) - printDeclaredAnnotation(SingleUser.class, Calendar.class); - printDeclaredAnnotation(SingleUser.class, Calendars.class); - - printDeclaredAnnotation(User.class, Calendar.class); - printDeclaredAnnotation(User.class, Calendars.class); - - printDeclaredAnnotation(UserComplex.class, Calendar.class); - printDeclaredAnnotation(UserComplex.class, Calendars.class); - - printDeclaredAnnotation(UserSub.class, Calendar.class); - printDeclaredAnnotation(UserSub.class, Calendars.class); - - printDeclaredAnnotation(UserSub2.class, Calendar.class); - printDeclaredAnnotation(UserSub2.class, Calendars.class); - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - } - - public static void testDeclaredAnnotationsByType() { - System.out.println("=============================="); - System.out.println("Declared class annotations by type:"); - System.out.println("=============================="); - - // A is directly present or repeatably present on an element E; - // -- (does not do any recursion for classes regardless of @Inherited) - printDeclaredAnnotationsByType(Calendar.class, SingleUser.class); - printDeclaredAnnotationsByType(Calendars.class, SingleUser.class); - - printDeclaredAnnotationsByType(Calendar.class, User.class); - printDeclaredAnnotationsByType(Calendars.class, User.class); - - printDeclaredAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y' - printDeclaredAnnotationsByType(Calendars.class, User2.class); - - printDeclaredAnnotationsByType(Calendar.class, UserComplex.class); - printDeclaredAnnotationsByType(Calendars.class, UserComplex.class); - - printDeclaredAnnotationsByType(Calendar.class, UserSub.class); - printDeclaredAnnotationsByType(Calendars.class, UserSub.class); - - printDeclaredAnnotationsByType(Calendar.class, UserSub2.class); - // The directly present "Calendar" annotation masks all the repeatably present "Calendar" - // annotations coming from User. - printDeclaredAnnotationsByType(Calendars.class, UserSub2.class); - // Edge case: UserSub2 doesn't directly have a Calendars annotation, - // so it doesn't mask the "User" Calendars annotation. - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - } - - // Print the annotation "annotationClass" that is associated with an element denoted by - // "annotationUseClass." - private static <A extends Annotation> void printAnnotationsByType(Class<A> annotationClass, - Class<?> annotationUseClass) { - A[] annotationsByType = annotationUseClass.getAnnotationsByType(annotationClass); - - String msg = "Annotations by type, defined by class " - + annotationUseClass.getName() + " with annotation " + annotationClass.getName() + ": " - + asString(annotationsByType); - - - System.out.println(msg); - } - - private static <A extends Annotation> void printDeclaredAnnotation(Class<?> annotationUseClass, - Class<A> annotationDefClass) { - A anno = annotationUseClass.getDeclaredAnnotation(annotationDefClass); - - String msg = asString(anno); - - System.out.println("Declared annotations by class " + annotationUseClass - + ", annotation " + annotationDefClass + ": " + msg); - } - - // Print the annotation "annotationClass" that is directly/indirectly present with an element - // denoted by "annotationUseClass." - private static <A extends Annotation> void printDeclaredAnnotationsByType( - Class<A> annotationClass, Class<?> annotationUseClass) { - A[] annotationsByType = annotationUseClass.getDeclaredAnnotationsByType(annotationClass); - - String msg = "Declared annnotations by type, defined by class " + annotationUseClass.getName() - + " with annotation " + annotationClass.getName() + ": " - + asString(annotationsByType); - - System.out.println(msg); - } - - public static void testMethodAnnotationsByType() { - System.out.println("=============================="); - System.out.println("Method annotations by type:"); - System.out.println("=============================="); - - // Print associated annotations: - // * A is directly present or repeatably present on an element E; - // * No annotation of A is directly/repeatably present on an element AND E is a class - // AND A's type is inheritable, AND A is associated with its superclass. - // (Looks through subtypes recursively only if there's 0 result at each level, - // and the annotation is @Inheritable). - printMethodAnnotationsByType(Calendar.class, "singleUser", AnnotationTestFixture.class); - printMethodAnnotationsByType(Calendars.class, "singleUser", AnnotationTestFixture.class); - - printMethodAnnotationsByType(Calendar.class, "user", AnnotationTestFixture.class); - printMethodAnnotationsByType(Calendars.class, "user", AnnotationTestFixture.class); - - printMethodAnnotationsByType(Calendar.class, "user2", AnnotationTestFixture.class); - printMethodAnnotationsByType(Calendars.class, "user2", AnnotationTestFixture.class); - - printMethodAnnotationsByType(Calendar.class, "userComplex", AnnotationTestFixture.class); - printMethodAnnotationsByType(Calendars.class, "userComplex", AnnotationTestFixture.class); - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - } - - // Print the annotation "annotationClass" that is associated with an element denoted by - // "annotationUseClass" method methodName. - private static <A extends Annotation> void printMethodAnnotationsByType(Class<A> annotationClass, - String methodName, Class<?> annotationUseClass) { - Method m = null; - try { - m = annotationUseClass.getDeclaredMethod(methodName); - } catch (Throwable t) { - throw new AssertionError(t); - } - A[] annotationsByType = m.getAnnotationsByType(annotationClass); - - String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " + - annotationClass.getName() + ": " + - asString(annotationsByType); - - System.out.println(msg); - } - - public static void testMethodDeclaredAnnotations() { - System.out.println("=============================="); - System.out.println("Declared method annotations:"); - System.out.println("=============================="); - - printMethodDeclaredAnnotation(Calendar.class, "singleUser", AnnotationTestFixture.class); - printMethodDeclaredAnnotation(Calendars.class, "singleUser", AnnotationTestFixture.class); - - printMethodDeclaredAnnotation(Calendar.class, "user", AnnotationTestFixture.class); - printMethodDeclaredAnnotation(Calendars.class, "user", AnnotationTestFixture.class); - - printMethodDeclaredAnnotation(Calendar.class, "user2", AnnotationTestFixture.class); - printMethodDeclaredAnnotation(Calendars.class, "user2", AnnotationTestFixture.class); - - printMethodDeclaredAnnotation(Calendar.class, "userComplex", AnnotationTestFixture.class); - printMethodDeclaredAnnotation(Calendars.class, "userComplex", AnnotationTestFixture.class); - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - } - - // Print the annotation "annotationClass" that is associated with an element denoted by - // methodName in annotationUseClass. - private static <A extends Annotation> void printMethodDeclaredAnnotation(Class<A> annotationClass, - String methodName, Class<?> annotationUseClass) { - Method m = null; - try { - m = annotationUseClass.getDeclaredMethod(methodName); - } catch (Throwable t) { - throw new AssertionError(t); - } - Annotation annotationsByType = m.getDeclaredAnnotation(annotationClass); - - String msg = "Annotations declared by method " + m.getName() + " with annotation " - + annotationClass.getName() + ": " - + asString(annotationsByType); - - System.out.println(msg); - } - - public static void testMethodDeclaredAnnotationsByType() { - System.out.println("=============================="); - System.out.println("Declared method annotations by type:"); - System.out.println("=============================="); - - printMethodDeclaredAnnotationByType(Calendar.class, "singleUser", AnnotationTestFixture.class); - printMethodDeclaredAnnotationByType(Calendars.class, "singleUser", AnnotationTestFixture.class); - - printMethodDeclaredAnnotationByType(Calendar.class, "user", AnnotationTestFixture.class); - printMethodDeclaredAnnotationByType(Calendars.class, "user", AnnotationTestFixture.class); - - printMethodDeclaredAnnotationByType(Calendar.class, "user2", AnnotationTestFixture.class); - printMethodDeclaredAnnotationByType(Calendars.class, "user2", AnnotationTestFixture.class); - - printMethodDeclaredAnnotationByType(Calendar.class, "userComplex", AnnotationTestFixture.class); - printMethodDeclaredAnnotationByType(Calendars.class, "userComplex", - AnnotationTestFixture.class); - - System.out.println("-----------------------------"); - System.out.println("-----------------------------"); - } - - // Print the annotation "annotationClass" that is associated with an element denoted by - // methodName in annotationUseClass. - private static <A extends Annotation> void printMethodDeclaredAnnotationByType( - Class<A> annotationClass, String methodName, Class<?> annotationUseClass) { - Method m = null; - try { - m = annotationUseClass.getDeclaredMethod(methodName); - } catch (Throwable t) { - throw new AssertionError(t); - } - A[] annotationsByType = m.getDeclaredAnnotationsByType(annotationClass); - - String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " - + annotationClass.getName() + ": " - + asString(annotationsByType); - - System.out.println(msg); - } -} diff --git a/test/048-reflect-v8/src/AnnotationTestFixture.java b/test/048-reflect-v8/src/AnnotationTestFixture.java deleted file mode 100644 index 248dfacf3b..0000000000 --- a/test/048-reflect-v8/src/AnnotationTestFixture.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 AnnotationTestFixture { - - @Calendar(dayOfWeek="single", hour=23) - public static void singleUser() { - - } - @Calendars ({ - @Calendar(dayOfMonth="last"), - @Calendar(dayOfWeek="Fri", hour=23) - }) - public static void user() { - - } - - @Calendars ({ - @Calendar(dayOfMonth="z"), - @Calendar(dayOfMonth="x"), - @Calendar(dayOfMonth="y") - }) - public static void user2() { - - } - - @Calendar(dayOfMonth="afirst") - @Calendars ({ - @Calendar(dayOfMonth="zsecond"), - @Calendar(dayOfMonth="athird", hour=23) - }) - public static void userComplex() { - - } -} diff --git a/test/048-reflect-v8/src/AnnotationTestHelpers.java b/test/048-reflect-v8/src/AnnotationTestHelpers.java deleted file mode 100644 index 6b5bea266e..0000000000 --- a/test/048-reflect-v8/src/AnnotationTestHelpers.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.annotation.Annotation; - -public class AnnotationTestHelpers { - // Provide custom print function that print a deterministic output. - // Note that Annotation#toString has unspecified order: it prints out the - // fields, which is why we can't rely on it. - - public static String asString(Annotation anno) { - if (anno instanceof Calendar) { - return asString((Calendar)anno); - } else if (anno instanceof Calendars) { - return asString((Calendars)anno); - } else { - if (anno == null) { - return "<null>"; - } - // Fall-back, usually would only go here in a test failure. - return anno.toString(); - } - } - - public static String asString(Annotation[] annos) { - String msg = ""; - - if (annos == null) { - msg += "<null>"; - } else if (annos.length == 0) { - msg += "<empty>"; - } else { - for (int i = 0; i < annos.length; ++i) { - msg += asString(annos[i]); - - if (i != annos.length - 1) { - msg += ", "; - } - } - } - - return msg; - } - - public static String asString(Calendar calendar) { - if (calendar == null) { - return "<null>"; - } - - return "@Calendar(dayOfMonth=" + calendar.dayOfMonth() + ", dayOfWeek=" + - calendar.dayOfWeek() + ", hour=" + calendar.hour() + ")"; - } - - public static String asString(Calendars calendars) { - if (calendars == null) { - return "<null>"; - } - - String s = "@Calendars(value=["; - - Calendar[] allValues = calendars.value(); - for (int i = 0; i < allValues.length; ++i) { - s += asString(allValues[i]); - if (i != allValues.length - 1) { - s += ", "; - } - } - - s += "])"; - - return s; - } -} diff --git a/test/048-reflect-v8/src/Calendar.java b/test/048-reflect-v8/src/Calendar.java deleted file mode 100644 index 4a16573bca..0000000000 --- a/test/048-reflect-v8/src/Calendar.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.annotation.Inherited; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -// This is a plain old non-1.8 annotation. At runtime we can see that it has a -// "Repeatable" annotation if we query with getDeclaredAnnotation(Repeatable.class) -@Retention(RetentionPolicy.RUNTIME) -@Repeatable(Calendars.class) -@Inherited // note: container must also be @Inherited by JLS. -public @interface Calendar { - String dayOfMonth() default "unspecified_month"; - String dayOfWeek() default "unspecified_week"; - int hour() default 6; -} - diff --git a/test/048-reflect-v8/src/IFaceSimple.java b/test/048-reflect-v8/src/IFaceSimple.java deleted file mode 100644 index 93cf61057e..0000000000 --- a/test/048-reflect-v8/src/IFaceSimple.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 annotation, no container. -@Calendar(dayOfMonth="if_simple_first") -public interface IFaceSimple { - -} diff --git a/test/048-reflect-v8/src/IsDefaultTest.java b/test/048-reflect-v8/src/IsDefaultTest.java deleted file mode 100644 index 177dcf1ab9..0000000000 --- a/test/048-reflect-v8/src/IsDefaultTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 IsDefaultTest { - interface DefaultInterface { - default void sayHi() { - System.out.println("hi default"); - } - } - - interface RegularInterface { - void sayHi(); - } - - class ImplementsWithDefault implements DefaultInterface {} - class ImplementsWithRegular implements RegularInterface { - public void sayHi() { - System.out.println("hello specific"); - } - } - - private static void printIsDefault(Class<?> klass) { - Method m; - try { - m = klass.getMethod("sayHi"); - } catch (Throwable t) { - System.out.println(t); - return; - } - - boolean isDefault = m.isDefault(); - System.out.println(klass.getName() + " is default = " + (isDefault ? "yes" : "no")); - } - - public static void test() { - System.out.println("=============================="); - System.out.println("Are These Methods Default:"); - System.out.println("=============================="); - - printIsDefault(DefaultInterface.class); - printIsDefault(RegularInterface.class); - printIsDefault(ImplementsWithDefault.class); - printIsDefault(ImplementsWithRegular.class); - } -} diff --git a/test/048-reflect-v8/src/Main.java b/test/048-reflect-v8/src/Main.java index f2b8287d18..7fa2a923d7 100644 --- a/test/048-reflect-v8/src/Main.java +++ b/test/048-reflect-v8/src/Main.java @@ -14,14 +14,43 @@ * limitations under the License. */ +import java.lang.reflect.Method; + public class Main { + interface DefaultInterface { + default void sayHi() { + System.out.println("hi default"); + } + } + + interface RegularInterface { + void sayHi(); + } + + class ImplementsWithDefault implements DefaultInterface {} + class ImplementsWithRegular implements RegularInterface { + public void sayHi() { + System.out.println("hello specific"); + } + } + + private static void printIsDefault(Class<?> klass) { + Method m; + try { + m = klass.getMethod("sayHi"); + } catch (Throwable t) { + System.out.println(t); + return; + } + + boolean isDefault = m.isDefault(); + System.out.println(klass.getName() + " is default = " + (isDefault ? "yes" : "no")); + } + public static void main(String[] args) { - IsDefaultTest.test(); - AnnotationTest.testAnnotationsByType(); - AnnotationTest.testDeclaredAnnotation(); - AnnotationTest.testDeclaredAnnotationsByType(); - AnnotationTest.testMethodAnnotationsByType(); - AnnotationTest.testMethodDeclaredAnnotations(); - AnnotationTest.testMethodDeclaredAnnotationsByType(); + printIsDefault(DefaultInterface.class); + printIsDefault(RegularInterface.class); + printIsDefault(ImplementsWithDefault.class); + printIsDefault(ImplementsWithRegular.class); } } diff --git a/test/048-reflect-v8/src/User.java b/test/048-reflect-v8/src/User.java deleted file mode 100644 index 003ceeb093..0000000000 --- a/test/048-reflect-v8/src/User.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -// Stored as a complex annotation Calendars(Calendar,Calendar) -// in the binary. -// -/* FIXME: Use this code instead, when Jack supports repeatable annotations properly. - * - * @Calendar(dayOfMonth="last") - * @Calendar(dayOfWeek="Fri", hour=23) - */ -@Calendars ({ - @Calendar(dayOfMonth="last"), - @Calendar(dayOfWeek="Fri", hour=23) -}) -public class User { - -} diff --git a/test/048-reflect-v8/src/User2.java b/test/048-reflect-v8/src/User2.java deleted file mode 100644 index 1a6049f508..0000000000 --- a/test/048-reflect-v8/src/User2.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -// Stored as a complex annotation Calendars(Calendar,Calendar,Calendar) -// in the binary. -// (Check for order, should be z,x,y) -@Calendars ({ - @Calendar(dayOfMonth="z"), - @Calendar(dayOfMonth="x"), - @Calendar(dayOfMonth="y") -}) -public class User2 { - -} diff --git a/test/048-reflect-v8/src/UserComplex.java b/test/048-reflect-v8/src/UserComplex.java deleted file mode 100644 index e26234960b..0000000000 --- a/test/048-reflect-v8/src/UserComplex.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -// Stored as a complex annotation Calendars(Calendar,Calendar) -// followed by a Calendar in the binary. -// In other words { Calendars([C,C]), C } -// -// Note that trying to do {C,Calendars,C} or similar -// is illegal by the JLS. -@Calendar(dayOfMonth="afirst") -@Calendars ({ - @Calendar(dayOfMonth="zsecond"), - @Calendar(dayOfMonth="athird", hour=23) -}) -// @Calendar(dayOfMonth="zlast") // Leave for future ordering test -public class UserComplex { - -} diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc index 1337442e5b..82e1fc8ae5 100644 --- a/test/117-nopatchoat/nopatchoat.cc +++ b/test/117-nopatchoat/nopatchoat.cc @@ -46,7 +46,7 @@ class NoPatchoatTest { return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable(); } - static bool isPic(jclass cls) { + static bool needsRelocation(jclass cls) { const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls); if (oat_dex_file == nullptr) { @@ -54,7 +54,7 @@ class NoPatchoatTest { } const OatFile* oat_file = oat_dex_file->GetOatFile(); - return oat_file->IsPic(); + return !oat_file->IsPic() && !oat_file->IsExtractOnly(); } }; @@ -66,8 +66,8 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasExecutableOat(JNIEnv*, jclass return NoPatchoatTest::hasExecutableOat(cls); } -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isPic(JNIEnv*, jclass cls) { - return NoPatchoatTest::isPic(cls); +extern "C" JNIEXPORT jboolean JNICALL Java_Main_needsRelocation(JNIEnv*, jclass cls) { + return NoPatchoatTest::needsRelocation(cls); } } // namespace art diff --git a/test/117-nopatchoat/src/Main.java b/test/117-nopatchoat/src/Main.java index 425cf4863f..816eb171a4 100644 --- a/test/117-nopatchoat/src/Main.java +++ b/test/117-nopatchoat/src/Main.java @@ -22,9 +22,9 @@ public class Main { // ANDROID_DATA has been relocated, since a non-relocated oat file always has a 0 delta. // Hitting this condition should be rare and ideally we would prevent it from happening but // there is no way to do so without major changes to the run-test framework. - boolean executable_correct = (isPic() ? - hasExecutableOat() == true : - hasExecutableOat() == (isDex2OatEnabled() || isRelocationDeltaZero())); + boolean executable_correct = (needsRelocation() ? + hasExecutableOat() == (isDex2OatEnabled() || isRelocationDeltaZero()) : + hasExecutableOat() == true); System.out.println( "dex2oat & patchoat are " + ((isDex2OatEnabled()) ? "enabled" : "disabled") + @@ -49,7 +49,7 @@ public class Main { private native static boolean isDex2OatEnabled(); - private native static boolean isPic(); + private native static boolean needsRelocation(); private native static boolean hasOatFile(); diff --git a/test/144-static-field-sigquit/expected.txt b/test/144-static-field-sigquit/expected.txt new file mode 100644 index 0000000000..e0c3e90221 --- /dev/null +++ b/test/144-static-field-sigquit/expected.txt @@ -0,0 +1,4 @@ +Starting threads... +Performing sigquits for 5 seconds +Got date field +Joined threads diff --git a/test/144-static-field-sigquit/info.txt b/test/144-static-field-sigquit/info.txt new file mode 100644 index 0000000000..5dcfc7603b --- /dev/null +++ b/test/144-static-field-sigquit/info.txt @@ -0,0 +1,8 @@ +Regression test for ag/853775 + +Tests that unresolved classes are not put into the dex cache by the verifier. +This was potentially happening when receiving a signal while in the static +initilizer of a class and also within a synchronized block. + +This test is flaky and produces the issue rarely, but it should be good enough +to trigger occasionally with the buildbots. diff --git a/test/048-reflect-v8/src/UserSub.java b/test/144-static-field-sigquit/src/ClassWithStaticField.java index d60aa6a3f1..0b2c8553f5 100644 --- a/test/048-reflect-v8/src/UserSub.java +++ b/test/144-static-field-sigquit/src/ClassWithStaticField.java @@ -14,8 +14,8 @@ * limitations under the License. */ -public class UserSub - extends User - implements IFaceA, IFaceSimple { +import java.util.Date; +public class ClassWithStaticField { + public static Date mDate = new Date(); } diff --git a/test/048-reflect-v8/src/SingleUser.java b/test/144-static-field-sigquit/src/Main.java index 0f9c430109..ab94da3ff3 100644 --- a/test/048-reflect-v8/src/SingleUser.java +++ b/test/144-static-field-sigquit/src/Main.java @@ -14,8 +14,19 @@ * limitations under the License. */ -// Stored as a single "Calendar" annotation in the binary. -@Calendar(dayOfWeek="single", hour=23) -public class SingleUser { +public class Main { + public static void main(String[] args) throws Exception { + Thread thread1 = new Thread(new SigQuit()); + Thread thread2 = new Thread(new SynchronizedUse()); + + System.out.println("Starting threads..."); + thread1.start(); + Thread.sleep(2000); + thread2.start(); + + thread1.join(); + thread2.join(); + System.out.println("Joined threads"); + } } diff --git a/test/144-static-field-sigquit/src/SigQuit.java b/test/144-static-field-sigquit/src/SigQuit.java new file mode 100644 index 0000000000..bed23e4a2d --- /dev/null +++ b/test/144-static-field-sigquit/src/SigQuit.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.*; + +public class SigQuit implements Runnable { + private final static int sigquit; + private final static Method kill; + private final static int pid; + + static { + int pidTemp = -1; + int sigquitTemp = -1; + Method killTemp = null; + + try { + Class<?> osClass = Class.forName("android.system.Os"); + Method getpid = osClass.getDeclaredMethod("getpid"); + pidTemp = (Integer) getpid.invoke(null); + + Class<?> osConstants = Class.forName("android.system.OsConstants"); + Field sigquitField = osConstants.getDeclaredField("SIGQUIT"); + sigquitTemp = (Integer) sigquitField.get(null); + + killTemp = osClass.getDeclaredMethod("kill", int.class, int.class); + } catch (Exception e) { + if (!e.getClass().getName().equals("ErrnoException")) { + e.printStackTrace(System.out); + } + } + + pid = pidTemp; + sigquit = sigquitTemp; + kill = killTemp; + } + + public boolean perform() { + try { + kill.invoke(null, pid, sigquit); + } catch (Exception e) { + if (!e.getClass().getName().equals("ErrnoException")) { + e.printStackTrace(System.out); + } + } + return true; + } + + public void run() { + long endTime = System.currentTimeMillis() + 5000; + System.out.println("Performing sigquits for 5 seconds"); + while (System.currentTimeMillis() < endTime) { + perform(); + } + } +} diff --git a/test/048-reflect-v8/src/UserSub2.java b/test/144-static-field-sigquit/src/SynchronizedUse.java index 13e2eb07c8..43af1d9c8d 100644 --- a/test/048-reflect-v8/src/UserSub2.java +++ b/test/144-static-field-sigquit/src/SynchronizedUse.java @@ -14,10 +14,13 @@ * limitations under the License. */ -// This calendar subsumes anything else we would've normally gotten from the subclass. -@Calendar(dayOfMonth="sub2") -public class UserSub2 - extends User - implements IFaceA, IFaceSimple { +import java.util.Date; +public class SynchronizedUse implements Runnable { + public void run() { + synchronized (this) { + Date dateField = ClassWithStaticField.mDate; + System.out.println("Got date field"); + } + } } diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java index 06cfd0a606..8f9a32ab3a 100644 --- a/test/449-checker-bce/src/Main.java +++ b/test/449-checker-bce/src/Main.java @@ -631,7 +631,8 @@ public class Main { /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>> /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>> /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>> - /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>] loop:<<InnerLoop>> + // Note: The ArtMethod* (typed as int or long) is optional after sharpening. + /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>> /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none @@ -644,7 +645,8 @@ public class Main { /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>> // Array reference ..[j] still in inner loop, with a direct index. /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>> - /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>] loop:<<InnerLoop>> + // Note: The ArtMethod* (typed as int or long) is optional after sharpening. + /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>> /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>> /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>> // Synthetic phi. diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java index f87326cc26..d647683869 100644 --- a/test/530-checker-lse/src/Main.java +++ b/test/530-checker-lse/src/Main.java @@ -664,19 +664,50 @@ public class Main { System.out.println("testFinalizableByForcingGc() failed to force gc."); } - public static void assertIntEquals(int expected, int result) { + /// CHECK-START: int Main.testHSelect(boolean) load_store_elimination (before) + /// CHECK: InstanceFieldSet + /// CHECK: Select + + /// CHECK-START: int Main.testHSelect(boolean) load_store_elimination (after) + /// CHECK: InstanceFieldSet + /// CHECK: Select + + // Test that HSelect creates alias. + public static int testHSelect(boolean b) { + // Disable inlining. + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + + TestClass obj = new TestClass(); + TestClass obj2 = null; + obj.i = 0xdead; + if (b) { + obj2 = obj; + } + return obj2.i; + } + + public static void assertIntEquals(int result, int expected) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } - public static void assertFloatEquals(float expected, float result) { + public static void assertFloatEquals(float result, float expected) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } - public static void assertDoubleEquals(double expected, double result) { + public static void assertDoubleEquals(double result, double expected) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } @@ -723,5 +754,6 @@ public class Main { assertIntEquals(test23(false), 5); assertFloatEquals(test24(), 8.0f); testFinalizableByForcingGc(); + assertIntEquals(testHSelect(true), 0xdead); } } diff --git a/test/563-checker-invoke-super/build b/test/563-checker-invoke-super/build new file mode 100755 index 0000000000..e06193ba78 --- /dev/null +++ b/test/563-checker-invoke-super/build @@ -0,0 +1,28 @@ +#!/bin/bash +# +# 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. +# Make us exit on a failure. +# +set -e + +# Hard-wired use of experimental jack. +# TODO: fix this temporary work-around for lambdas, see b/19467889 +export USE_JACK=true +export JACK_SERVER=false +export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks" + +# e.g. /foo/bar/jack-3.10.ALPHA.jar -> 3.10.ALPHA +export JACK_VERSION="$(find "$JACK_REPOSITORY" -name '*ALPHA*' | sed 's/.*jack-//g' | sed 's/[.]jar//g')" +./default-build "$@" --experimental default-methods diff --git a/test/563-checker-invoke-super/expected.txt b/test/563-checker-invoke-super/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/563-checker-invoke-super/expected.txt diff --git a/test/563-checker-invoke-super/info.txt b/test/563-checker-invoke-super/info.txt new file mode 100644 index 0000000000..23c0d2fa49 --- /dev/null +++ b/test/563-checker-invoke-super/info.txt @@ -0,0 +1,2 @@ +Tests that invoke-super's to interface methods are optimized to direct method +calls when in the same dex file. diff --git a/test/563-checker-invoke-super/src/Main.java b/test/563-checker-invoke-super/src/Main.java new file mode 100644 index 0000000000..8554dbd0ec --- /dev/null +++ b/test/563-checker-invoke-super/src/Main.java @@ -0,0 +1,39 @@ +/* + * 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. + */ + +interface IFace { + public default void $noinline$aMethod() { throw new RuntimeException("Should not be called"); } +} + +class ClassImplA implements IFace { + /// CHECK-START: void ClassImplA.testSuperInvoke() builder (after) + /// CHECK: InvokeStaticOrDirect + public void testSuperInvoke() { + IFace.super.$noinline$aMethod(); + } +} + +class ClassImplB extends ClassImplA { + /// CHECK-START: void ClassImplB.testSuperInvoke2() builder (after) + /// CHECK: InvokeStaticOrDirect + public void testSuperInvoke2() { + super.$noinline$aMethod(); + } +} + +public class Main { + public static void main(String[] args) { } +} diff --git a/test/565-checker-doublenegbitwise/expected.txt b/test/565-checker-doublenegbitwise/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/565-checker-doublenegbitwise/expected.txt diff --git a/test/565-checker-doublenegbitwise/info.txt b/test/565-checker-doublenegbitwise/info.txt new file mode 100644 index 0000000000..cbe183c405 --- /dev/null +++ b/test/565-checker-doublenegbitwise/info.txt @@ -0,0 +1 @@ +Test double-negated bitwise operations simplifications. diff --git a/test/565-checker-doublenegbitwise/src/Main.java b/test/565-checker-doublenegbitwise/src/Main.java new file mode 100644 index 0000000000..d681ad7e8e --- /dev/null +++ b/test/565-checker-doublenegbitwise/src/Main.java @@ -0,0 +1,211 @@ +/* +* 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 { + + // A dummy value to defeat inlining of these routines. + static boolean doThrow = false; + + public static void assertIntEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void assertLongEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + /** + * Test transformation of Not/Not/And into Or/Not. + */ + + // Note: before the instruction_simplifier pass, Xor's are used instead of + // Not's (the simplification happens during the same pass). + /// CHECK-START-ARM64: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<CstM1:i\d+>> IntConstant -1 + /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] + /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] + /// CHECK: <<And:i\d+>> And [<<Not1>>,<<Not2>>] + /// CHECK: Return [<<And>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<Or:i\d+>> Or [<<P1>>,<<P2>>] + /// CHECK: <<Not:i\d+>> Not [<<Or>>] + /// CHECK: Return [<<Not>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after) + /// CHECK: Not + /// CHECK-NOT: Not + /// CHECK-NOT: And + + public static int $opt$noinline$andToOr(int a, int b) { + if (doThrow) throw new Error(); + return ~a & ~b; + } + + /** + * Test transformation of Not/Not/Or into And/Not. + */ + + // See note above. + // The second Xor has its arguments reversed for no obvious reason. + /// CHECK-START-ARM64: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before) + /// CHECK: <<P1:j\d+>> ParameterValue + /// CHECK: <<P2:j\d+>> ParameterValue + /// CHECK: <<CstM1:j\d+>> LongConstant -1 + /// CHECK: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>] + /// CHECK: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>] + /// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>] + /// CHECK: Return [<<Or>>] + + /// CHECK-START-ARM64: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after) + /// CHECK: <<P1:j\d+>> ParameterValue + /// CHECK: <<P2:j\d+>> ParameterValue + /// CHECK: <<And:j\d+>> And [<<P1>>,<<P2>>] + /// CHECK: <<Not:j\d+>> Not [<<And>>] + /// CHECK: Return [<<Not>>] + + /// CHECK-START-ARM64: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after) + /// CHECK: Not + /// CHECK-NOT: Not + /// CHECK-NOT: Or + + public static long $opt$noinline$orToAnd(long a, long b) { + if (doThrow) throw new Error(); + return ~a | ~b; + } + + /** + * Test that the transformation copes with inputs being separated from the + * bitwise operations. + * This is a regression test. The initial logic was inserting the new bitwise + * operation incorrectly. + */ + + /// CHECK-START-ARM64: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 + /// CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 + /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] + /// CHECK: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>] + /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] + /// CHECK: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>] + /// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>] + /// CHECK: Return [<<Or>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<Cst1:i\d+>> IntConstant 1 + /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] + /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] + /// CHECK: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>] + /// CHECK: <<Not:i\d+>> Not [<<And>>] + /// CHECK: Return [<<Not>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after) + /// CHECK: Not + /// CHECK-NOT: Not + /// CHECK-NOT: Or + + public static int $opt$noinline$regressInputsAway(int a, int b) { + if (doThrow) throw new Error(); + int a1 = a + 1; + int not_a1 = ~a1; + int b1 = b + 1; + int not_b1 = ~b1; + return not_a1 | not_b1; + } + + /** + * Test transformation of Not/Not/Xor into Xor. + */ + + // See first note above. + /// CHECK-START-ARM64: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<CstM1:i\d+>> IntConstant -1 + /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] + /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] + /// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>] + /// CHECK: Return [<<Xor>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>] + /// CHECK: Return [<<Xor>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after) + /// CHECK-NOT: Not + + public static int $opt$noinline$notXorToXor(int a, int b) { + if (doThrow) throw new Error(); + return ~a ^ ~b; + } + + /** + * Check that no transformation is done when one Not has multiple uses. + */ + + /// CHECK-START-ARM64: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<CstM1:i\d+>> IntConstant -1 + /// CHECK: <<One:i\d+>> IntConstant 1 + /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] + /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>] + /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] + /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] + /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>] + /// CHECK: Return [<<Add>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after) + /// CHECK: <<P1:i\d+>> ParameterValue + /// CHECK: <<P2:i\d+>> ParameterValue + /// CHECK: <<One:i\d+>> IntConstant 1 + /// CHECK: <<Not2:i\d+>> Not [<<P2>>] + /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>] + /// CHECK: <<Not1:i\d+>> Not [<<P1>>] + /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] + /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>] + /// CHECK: Return [<<Add>>] + + /// CHECK-START-ARM64: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after) + /// CHECK-NOT: Or + + public static int $opt$noinline$notMultipleUses(int a, int b) { + if (doThrow) throw new Error(); + int tmp = ~b; + return (tmp & 0x1) + (~a & tmp); + } + + public static void main(String[] args) { + assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff)); + assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff)); + assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff)); + assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff)); + } +} diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc index 55eac5c30a..b2934ed163 100644 --- a/test/566-polymorphic-inlining/polymorphic_inline.cc +++ b/test/566-polymorphic-inlining/polymorphic_inline.cc @@ -29,11 +29,18 @@ static void do_checks(jclass cls, const char* method_name) { jit::Jit* jit = Runtime::Current()->GetJit(); jit::JitCodeCache* code_cache = jit->GetCodeCache(); ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, sizeof(void*)); - jit->CompileMethod(method, soa.Self()); - OatQuickMethodHeader* header = OatQuickMethodHeader::FromEntryPoint( - method->GetEntryPointFromQuickCompiledCode()); - CHECK(code_cache->ContainsPc(header->GetCode())); + OatQuickMethodHeader* header = nullptr; + // Infinite loop... Test harness will have its own timeout. + while (true) { + header = OatQuickMethodHeader::FromEntryPoint(method->GetEntryPointFromQuickCompiledCode()); + if (code_cache->ContainsPc(header->GetCode())) { + break; + } else { + // sleep one second to give time to the JIT compiler. + sleep(1); + } + } CodeInfo info = header->GetOptimizedCodeInfo(); CHECK(info.HasInlineInfo()); @@ -45,6 +52,11 @@ extern "C" JNIEXPORT void JNICALL Java_Main_ensureJittedAndPolymorphicInline(JNI return; } + if (kIsDebugBuild) { + // A debug build might often compile the methods without profiling informations filled. + return; + } + do_checks(cls, "testInvokeVirtual"); do_checks(cls, "testInvokeInterface"); } diff --git a/test/568-checker-onebit/src/Main.java b/test/568-checker-onebit/src/Main.java index 7007c6a507..6ce4ffbd3f 100644 --- a/test/568-checker-onebit/src/Main.java +++ b/test/568-checker-onebit/src/Main.java @@ -45,6 +45,10 @@ public class Main { } public static void main(String args[]) { + // Hidden zeros. + int[] xi = new int[32]; + long[] xj = new long[64]; + expectEquals32(0x00000000, hi32(0x00000000)); expectEquals32(0x00000000, lo32(0x00000000)); expectEquals32(0x00010000, hi32(0x00010000)); @@ -55,6 +59,8 @@ public class Main { expectEquals32(0x00000001, lo32(0xFFFFFFFF)); for (int i = 0; i < 32; i++) { + expectEquals32(0, hi32(xi[i])); + expectEquals32(0, lo32(xi[i])); expectEquals32(1 << i, hi32(1 << i)); expectEquals32(1 << i, lo32(1 << i)); int expected = i < 29 ? 0x8 << i : 0x80000000; @@ -72,6 +78,8 @@ public class Main { expectEquals64(0x0000000000000001L, lo64(0xFFFFFFFFFFFFFFFFL)); for (int i = 0; i < 64; i++) { + expectEquals64(0L, hi64(xj[i])); + expectEquals64(0L, lo64(xj[i])); expectEquals64(1L << i, hi64(1L << i)); expectEquals64(1L << i, lo64(1L << i)); long expected = i < 61 ? 0x8L << i : 0x8000000000000000L; diff --git a/test/569-checker-pattern-replacement/src/Main.java b/test/569-checker-pattern-replacement/src/Main.java index 9a85c81249..e2d451cc86 100644 --- a/test/569-checker-pattern-replacement/src/Main.java +++ b/test/569-checker-pattern-replacement/src/Main.java @@ -39,7 +39,8 @@ public class Main { /// CHECK-DAG: <<Value:l\d+>> ParameterValue /// CHECK-DAG: <<Ignored:i\d+>> IntConstant 77 /// CHECK-DAG: <<ClinitCk:l\d+>> ClinitCheck - /// CHECK-DAG: <<Invoke:l\d+>> InvokeStaticOrDirect [<<Ignored>>,<<Value>>,<<ClinitCk>>] + // Note: The ArtMethod* (typed as int or long) is optional after sharpening. + /// CHECK-DAG: <<Invoke:l\d+>> InvokeStaticOrDirect [<<Ignored>>,<<Value>>{{(,[ij]\d+)?}},<<ClinitCk>>] /// CHECK-DAG: Return [<<Invoke>>] /// CHECK-START: java.lang.Object Main.staticReturnArg2(java.lang.String) inliner (after) @@ -313,7 +314,8 @@ public class Main { /// CHECK-START: java.lang.Object Main.newObject() inliner (before) /// CHECK-DAG: <<Obj:l\d+>> NewInstance - /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>] method_name:java.lang.Object.<init> + // Note: The ArtMethod* (typed as int or long) is optional after sharpening. + /// CHECK-DAG: InvokeStaticOrDirect [<<Obj>>{{(,[ij]\d+)?}}] method_name:java.lang.Object.<init> /// CHECK-START: java.lang.Object Main.newObject() inliner (after) /// CHECK-NOT: InvokeStaticOrDirect diff --git a/test/570-checker-select/expected.txt b/test/570-checker-select/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/570-checker-select/expected.txt diff --git a/test/570-checker-select/info.txt b/test/570-checker-select/info.txt new file mode 100644 index 0000000000..6d49532ece --- /dev/null +++ b/test/570-checker-select/info.txt @@ -0,0 +1 @@ +Tests for HSelect codegens. diff --git a/test/570-checker-select/src/Main.java b/test/570-checker-select/src/Main.java new file mode 100644 index 0000000000..2f8094de96 --- /dev/null +++ b/test/570-checker-select/src/Main.java @@ -0,0 +1,195 @@ +/* + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.BoolCond_IntVarVar(boolean, int, int) register (after) + /// CHECK: Select [{{i\d+}},{{i\d+}},{{z\d+}}] + + public static int BoolCond_IntVarVar(boolean cond, int x, int y) { + return cond ? x : y; + } + + /// CHECK-START: int Main.BoolCond_IntVarCst(boolean, int) register (after) + /// CHECK: Select [{{i\d+}},{{i\d+}},{{z\d+}}] + + public static int BoolCond_IntVarCst(boolean cond, int x) { + return cond ? x : 1; + } + + /// CHECK-START: int Main.BoolCond_IntCstVar(boolean, int) register (after) + /// CHECK: Select [{{i\d+}},{{i\d+}},{{z\d+}}] + + public static int BoolCond_IntCstVar(boolean cond, int y) { + return cond ? 1 : y; + } + + /// CHECK-START: float Main.BoolCond_FloatVarVar(boolean, float, float) register (after) + /// CHECK: Select [{{f\d+}},{{f\d+}},{{z\d+}}] + + public static float BoolCond_FloatVarVar(boolean cond, float x, float y) { + return cond ? x : y; + } + + /// CHECK-START: float Main.BoolCond_FloatVarCst(boolean, float) register (after) + /// CHECK: Select [{{f\d+}},{{f\d+}},{{z\d+}}] + + public static float BoolCond_FloatVarCst(boolean cond, float x) { + return cond ? x : 1.0f; + } + + /// CHECK-START: float Main.BoolCond_FloatCstVar(boolean, float) register (after) + /// CHECK: Select [{{f\d+}},{{f\d+}},{{z\d+}}] + + public static float BoolCond_FloatCstVar(boolean cond, float y) { + return cond ? 1.0f : y; + } + + /// CHECK-START: int Main.IntNonmatCond_IntVarVar(int, int, int, int) register (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK-NEXT: Select [{{i\d+}},{{i\d+}},<<Cond>>] + + public static int IntNonmatCond_IntVarVar(int a, int b, int x, int y) { + return a > b ? x : y; + } + + /// CHECK-START: int Main.IntMatCond_IntVarVar(int, int, int, int) register (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{i\d+}},{{i\d+}}] + /// CHECK-NEXT: <<Sel:i\d+>> Select [{{i\d+}},{{i\d+}},{{z\d+}}] + /// CHECK-NEXT: Add [<<Cond>>,<<Sel>>] + + 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); + } + + /// CHECK-START: int Main.FloatLtNonmatCond_IntVarVar(float, float, int, int) register (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{f\d+}},{{f\d+}}] + /// CHECK-NEXT: Select [{{i\d+}},{{i\d+}},<<Cond>>] + + public static int FloatLtNonmatCond_IntVarVar(float a, float b, int x, int y) { + return a > b ? x : y; + } + + /// CHECK-START: int Main.FloatGtNonmatCond_IntVarVar(float, float, int, int) register (after) + /// CHECK: <<Cond:z\d+>> GreaterThanOrEqual [{{f\d+}},{{f\d+}}] + /// CHECK-NEXT: Select [{{i\d+}},{{i\d+}},<<Cond>>] + + public static int FloatGtNonmatCond_IntVarVar(float a, float b, int x, int y) { + return a < b ? x : y; + } + + /// CHECK-START: float Main.FloatGtNonmatCond_FloatVarVar(float, float, float, float) register (after) + /// CHECK: <<Cond:z\d+>> GreaterThanOrEqual [{{f\d+}},{{f\d+}}] + /// CHECK-NEXT: Select [{{f\d+}},{{f\d+}},<<Cond>>] + + public static float FloatGtNonmatCond_FloatVarVar(float a, float b, float x, float y) { + return a < b ? x : y; + } + + /// CHECK-START: int Main.FloatLtMatCond_IntVarVar(float, float, int, int) register (after) + /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{f\d+}},{{f\d+}}] + /// CHECK-NEXT: <<Sel:i\d+>> Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK-NEXT: Add [<<Cond>>,<<Sel>>] + + public static int FloatLtMatCond_IntVarVar(float a, float b, int x, int y) { + int result = (a > b ? x : y); + return result + (a > b ? 0 : 1); + } + + /// CHECK-START: int Main.FloatGtMatCond_IntVarVar(float, float, int, int) register (after) + /// CHECK: <<Cond:z\d+>> GreaterThanOrEqual [{{f\d+}},{{f\d+}}] + /// CHECK-NEXT: <<Sel:i\d+>> Select [{{i\d+}},{{i\d+}},<<Cond>>] + /// CHECK-NEXT: Add [<<Cond>>,<<Sel>>] + + public static int FloatGtMatCond_IntVarVar(float a, float b, int x, int y) { + int result = (a < b ? x : y); + return result + (a < b ? 0 : 1); + } + + /// CHECK-START: float Main.FloatGtMatCond_FloatVarVar(float, float, float, float) register (after) + /// CHECK: <<Cond:z\d+>> GreaterThanOrEqual + /// CHECK-NEXT: <<Sel:f\d+>> Select [{{f\d+}},{{f\d+}},<<Cond>>] + /// CHECK-NEXT: TypeConversion [<<Cond>>] + + public static float FloatGtMatCond_FloatVarVar(float a, float b, float x, float y) { + float result = (a < b ? x : y); + return result + (a < b ? 0 : 1); + } + + public static void assertEqual(int expected, int actual) { + if (expected != actual) { + throw new Error("Assertion failed: " + expected + " != " + actual); + } + } + + public static void assertEqual(float expected, float actual) { + if (expected != actual) { + throw new Error("Assertion failed: " + expected + " != " + actual); + } + } + + public static void main(String[] args) { + assertEqual(5, BoolCond_IntVarVar(true, 5, 7)); + assertEqual(7, BoolCond_IntVarVar(false, 5, 7)); + assertEqual(5, BoolCond_IntVarCst(true, 5)); + assertEqual(1, BoolCond_IntVarCst(false, 5)); + assertEqual(1, BoolCond_IntCstVar(true, 7)); + assertEqual(7, BoolCond_IntCstVar(false, 7)); + + assertEqual(5, BoolCond_FloatVarVar(true, 5, 7)); + assertEqual(7, BoolCond_FloatVarVar(false, 5, 7)); + assertEqual(5, BoolCond_FloatVarCst(true, 5)); + assertEqual(1, BoolCond_FloatVarCst(false, 5)); + assertEqual(1, BoolCond_FloatCstVar(true, 7)); + assertEqual(7, BoolCond_FloatCstVar(false, 7)); + + assertEqual(5, IntNonmatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(7, IntNonmatCond_IntVarVar(2, 3, 5, 7)); + assertEqual(5, IntMatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(8, IntMatCond_IntVarVar(2, 3, 5, 7)); + + assertEqual(5, FloatLtNonmatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(7, FloatLtNonmatCond_IntVarVar(2, 3, 5, 7)); + assertEqual(7, FloatLtNonmatCond_IntVarVar(Float.NaN, 2, 5, 7)); + assertEqual(7, FloatLtNonmatCond_IntVarVar(2, Float.NaN, 5, 7)); + + assertEqual(5, FloatGtNonmatCond_IntVarVar(2, 3, 5, 7)); + assertEqual(7, FloatGtNonmatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(7, FloatGtNonmatCond_IntVarVar(Float.NaN, 2, 5, 7)); + assertEqual(7, FloatGtNonmatCond_IntVarVar(2, Float.NaN, 5, 7)); + + assertEqual(5, FloatGtNonmatCond_FloatVarVar(2, 3, 5, 7)); + assertEqual(7, FloatGtNonmatCond_FloatVarVar(3, 2, 5, 7)); + assertEqual(7, FloatGtNonmatCond_FloatVarVar(Float.NaN, 2, 5, 7)); + assertEqual(7, FloatGtNonmatCond_FloatVarVar(2, Float.NaN, 5, 7)); + + assertEqual(5, FloatLtMatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(8, FloatLtMatCond_IntVarVar(2, 3, 5, 7)); + assertEqual(8, FloatLtMatCond_IntVarVar(Float.NaN, 2, 5, 7)); + assertEqual(8, FloatLtMatCond_IntVarVar(2, Float.NaN, 5, 7)); + + assertEqual(5, FloatGtMatCond_IntVarVar(2, 3, 5, 7)); + assertEqual(8, FloatGtMatCond_IntVarVar(3, 2, 5, 7)); + assertEqual(8, FloatGtMatCond_IntVarVar(Float.NaN, 2, 5, 7)); + assertEqual(8, FloatGtMatCond_IntVarVar(2, Float.NaN, 5, 7)); + + assertEqual(5, FloatGtMatCond_FloatVarVar(2, 3, 5, 7)); + assertEqual(8, FloatGtMatCond_FloatVarVar(3, 2, 5, 7)); + assertEqual(8, FloatGtMatCond_FloatVarVar(Float.NaN, 2, 5, 7)); + assertEqual(8, FloatGtMatCond_FloatVarVar(2, Float.NaN, 5, 7)); + } +} diff --git a/test/571-irreducible-loop/expected.txt b/test/571-irreducible-loop/expected.txt new file mode 100644 index 0000000000..3a71184143 --- /dev/null +++ b/test/571-irreducible-loop/expected.txt @@ -0,0 +1 @@ +5.9E-44 diff --git a/test/571-irreducible-loop/info.txt b/test/571-irreducible-loop/info.txt new file mode 100644 index 0000000000..1e0dd02284 --- /dev/null +++ b/test/571-irreducible-loop/info.txt @@ -0,0 +1,2 @@ +Regression test for optimizing in the presence of +an irreducible loop. diff --git a/test/571-irreducible-loop/smali/IrreducibleLoop.smali b/test/571-irreducible-loop/smali/IrreducibleLoop.smali new file mode 100644 index 0000000000..737a18b5cb --- /dev/null +++ b/test/571-irreducible-loop/smali/IrreducibleLoop.smali @@ -0,0 +1,47 @@ +# 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; + +# Check that on x86 we don't crash because irreducible loops +# disabled the constant pool optimization. +.method public static test1(IF)F + .registers 5 + const/16 v0, 1 + const/16 v1, 42 + + if-nez p0, :loop_entry + goto :other_loop_pre_entry + + # The then part: beginning of the irreducible loop. + :loop_entry + if-eqz p0, :exit + add-float v2, p1, v1 + sub-float v2, v2, v1 + div-float v2, v2, v1 + mul-float v2, v2, v1 + :other_loop_entry + sub-int p0, p0, v0 + goto :loop_entry + + # The other block branching to the irreducible loop. + # In that block, v4 has no live range. + :other_loop_pre_entry + goto :other_loop_entry + + :exit + return v1 +.end method diff --git a/test/048-reflect-v8/src/Calendars.java b/test/571-irreducible-loop/src/Main.java index caeda52ea6..ff22f6720f 100644 --- a/test/048-reflect-v8/src/Calendars.java +++ b/test/571-irreducible-loop/src/Main.java @@ -14,13 +14,16 @@ * limitations under the License. */ -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; -// Plain old annotation, there's nothing 1.8 specific about it. -@Retention(RetentionPolicy.RUNTIME) -@Inherited // note: elements must also be @Inherited by JLS. -public @interface Calendars { - Calendar[] value(); +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("test1", int.class, float.class); + Object[] arguments = { 42, 31.0f }; + System.out.println(m.invoke(null, arguments)); + } } diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt index 2e66af59e7..73ce3073ce 100644 --- a/test/800-smali/expected.txt +++ b/test/800-smali/expected.txt @@ -50,4 +50,12 @@ b/25494456 b/21869691 b/26143249 b/26579108 +b/26594149 (1) +b/26594149 (2) +b/26594149 (3) +b/26594149 (4) +b/26594149 (5) +b/26594149 (6) +b/26594149 (7) +b/26594149 (8) Done! diff --git a/test/800-smali/smali/b_26594149_1.smali b/test/800-smali/smali/b_26594149_1.smali new file mode 100644 index 0000000000..c465859312 --- /dev/null +++ b/test/800-smali/smali/b_26594149_1.smali @@ -0,0 +1,26 @@ +# 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 LB26594149_1; +.super Ljava/lang/Object; + +.method public static run()V + .registers 2 + new-instance v0, Ljava/lang/String; + + # Illegal operation. + instance-of v1, v0, Ljava/lang/String; + + return-void + .end method diff --git a/test/800-smali/smali/b_26594149_2.smali b/test/800-smali/smali/b_26594149_2.smali new file mode 100644 index 0000000000..765afe2610 --- /dev/null +++ b/test/800-smali/smali/b_26594149_2.smali @@ -0,0 +1,26 @@ +# 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 LB26594149_2; +.super Ljava/lang/Object; + +.method public static run()V + .registers 2 + new-instance v0, Ljava/lang/String; + + # Illegal operation. + check-cast v0, Ljava/lang/String; + + return-void + .end method diff --git a/test/800-smali/smali/b_26594149_3.smali b/test/800-smali/smali/b_26594149_3.smali new file mode 100644 index 0000000000..42b5675149 --- /dev/null +++ b/test/800-smali/smali/b_26594149_3.smali @@ -0,0 +1,28 @@ +# 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 LB26594149_3; +.super Ljava/lang/Object; + +.field public static field:Ljava/lang/String; + +.method public static run()V + .registers 2 + new-instance v0, Ljava/lang/String; + + # Illegal operation. + sput-object v0, LB26594149_3;->field:Ljava/lang/String; + + return-void + .end method diff --git a/test/800-smali/smali/b_26594149_4.smali b/test/800-smali/smali/b_26594149_4.smali new file mode 100644 index 0000000000..5b2f99bf37 --- /dev/null +++ b/test/800-smali/smali/b_26594149_4.smali @@ -0,0 +1,38 @@ +# 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 LB26594149_4; +.super Ljava/lang/Object; + +.field public field:Ljava/lang/String; + +.method public constructor <init>()V + .registers 4 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method public static run()V + .registers 4 + + new-instance v1, LB26594149_4; + invoke-direct {v1}, LB26594149_4;-><init>()V + + new-instance v0, Ljava/lang/String; + + # Illegal operation. + iput-object v0, v1, LB26594149_4;->field:Ljava/lang/String; + + return-void + .end method diff --git a/test/800-smali/smali/b_26594149_5.smali b/test/800-smali/smali/b_26594149_5.smali new file mode 100644 index 0000000000..27d6255f82 --- /dev/null +++ b/test/800-smali/smali/b_26594149_5.smali @@ -0,0 +1,28 @@ +# 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 LB26594149_5; +.super Ljava/lang/Object; + +.method public static run()V + .registers 4 + + new-instance v0, Ljava/lang/Object; + + # Allowed operation on uninitialized objects. + monitor-enter v0 + monitor-exit v0 + + return-void + .end method diff --git a/test/800-smali/smali/b_26594149_6.smali b/test/800-smali/smali/b_26594149_6.smali new file mode 100644 index 0000000000..8d26ee8c58 --- /dev/null +++ b/test/800-smali/smali/b_26594149_6.smali @@ -0,0 +1,24 @@ +# 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 LB26594149_6; +.super Ljava/lang/Object; + +.method public static run()V + .registers 4 + + new-instance v0, Ljava/lang/Exception; + throw v0 + + .end method diff --git a/test/800-smali/smali/b_26594149_7.smali b/test/800-smali/smali/b_26594149_7.smali new file mode 100644 index 0000000000..f624d1adec --- /dev/null +++ b/test/800-smali/smali/b_26594149_7.smali @@ -0,0 +1,30 @@ +# 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 LB26594149_7; +.super Ljava/lang/Object; + +.method private static foo(Ljava/lang/Object;)V + .registers 1 + return-void +.end method + +.method public static run()V + .registers 4 + + new-instance v0, Ljava/lang/Object; + invoke-static {v0}, LB26594149_7;->foo(Ljava/lang/Object;)V + return-void + + .end method diff --git a/test/800-smali/smali/b_26594149_8.smali b/test/800-smali/smali/b_26594149_8.smali new file mode 100644 index 0000000000..e366de42eb --- /dev/null +++ b/test/800-smali/smali/b_26594149_8.smali @@ -0,0 +1,24 @@ +# 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 LB26594149_8; +.super Ljava/lang/Object; + +.method public static run()Ljava/lang/Object; + .registers 4 + + new-instance v0, Ljava/lang/Object; + return-object v0 + + .end method diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java index 38aa58de77..b0eff5d0bd 100644 --- a/test/800-smali/src/Main.java +++ b/test/800-smali/src/Main.java @@ -145,6 +145,21 @@ public class Main { new AbstractMethodError(), null)); testCases.add(new TestCase("b/26579108", "B26579108", "run", null, new VerifyError(), null)); + testCases.add(new TestCase("b/26594149 (1)", "B26594149_1", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (2)", "B26594149_2", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (3)", "B26594149_3", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (4)", "B26594149_4", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (5)", "B26594149_5", "run", null, null, null)); + testCases.add(new TestCase("b/26594149 (6)", "B26594149_6", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (7)", "B26594149_7", "run", null, new VerifyError(), + null)); + testCases.add(new TestCase("b/26594149 (8)", "B26594149_8", "run", null, new VerifyError(), + null)); } public void runTests() { diff --git a/test/972-iface-super-multidex/expected.txt b/test/972-iface-super-multidex/expected.txt new file mode 100644 index 0000000000..a9d31a5320 --- /dev/null +++ b/test/972-iface-super-multidex/expected.txt @@ -0,0 +1,2 @@ +SuperInterface default method called +Expected ICCE caught diff --git a/test/972-iface-super-multidex/info.txt b/test/972-iface-super-multidex/info.txt new file mode 100644 index 0000000000..f7948ad2a5 --- /dev/null +++ b/test/972-iface-super-multidex/info.txt @@ -0,0 +1,3 @@ +Smali-based tests for experimental interface default methods. + +Obviously needs to run under ART or a Java 8 Language runtime and compiler. diff --git a/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali b/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali new file mode 100644 index 0000000000..2c76213015 --- /dev/null +++ b/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali @@ -0,0 +1,23 @@ +# +# 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 abstract interface LConflictInterface; +.super Ljava/lang/Object; +.implements LOneConflict; +.implements LTwoConflict; + +# public interface ConflictInterface extends OneConflict, TwoConflict { +# } diff --git a/test/972-iface-super-multidex/smali-multidex/oneconflict.smali b/test/972-iface-super-multidex/smali-multidex/oneconflict.smali new file mode 100644 index 0000000000..7001f02c0f --- /dev/null +++ b/test/972-iface-super-multidex/smali-multidex/oneconflict.smali @@ -0,0 +1,31 @@ +# +# 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 abstract interface LOneConflict; +.super Ljava/lang/Object; + +# public interface OneConflict { +# public String runDefault() { +# return "OneConflict default method called"; +# } +# } + +.method public runDefault()Ljava/lang/String; +.registers 2 + # Do an invoke super on this class, to confuse runtime/compiler. + const-string v0, "OneConflict default method called" + return-object v0 +.end method diff --git a/test/972-iface-super-multidex/smali-multidex/superinterface.smali b/test/972-iface-super-multidex/smali-multidex/superinterface.smali new file mode 100644 index 0000000000..d45ecea045 --- /dev/null +++ b/test/972-iface-super-multidex/smali-multidex/superinterface.smali @@ -0,0 +1,31 @@ +# +# 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 abstract interface LSuperInterface; +.super Ljava/lang/Object; + +# public interface SuperInterface { +# public String runDefault() { +# return "SuperInterface default method called"; +# } +# } + +.method public runDefault()Ljava/lang/String; +.registers 2 + # Do an invoke super on this class, to confuse runtime/compiler. + const-string v0, "SuperInterface default method called" + return-object v0 +.end method diff --git a/test/972-iface-super-multidex/smali-multidex/twoconflict.smali b/test/972-iface-super-multidex/smali-multidex/twoconflict.smali new file mode 100644 index 0000000000..b971b74649 --- /dev/null +++ b/test/972-iface-super-multidex/smali-multidex/twoconflict.smali @@ -0,0 +1,31 @@ +# +# 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 abstract interface LTwoConflict; +.super Ljava/lang/Object; + +# public interface TwoConflict { +# public String runDefault() { +# return "TwoConflict default method called"; +# } +# } + +.method public runDefault()Ljava/lang/String; +.registers 2 + # Do an invoke super on this class, to confuse runtime/compiler. + const-string v0, "TwoConflict default method called" + return-object v0 +.end method diff --git a/test/972-iface-super-multidex/smali/concreteclass.smali b/test/972-iface-super-multidex/smali/concreteclass.smali new file mode 100644 index 0000000000..703da945cc --- /dev/null +++ b/test/972-iface-super-multidex/smali/concreteclass.smali @@ -0,0 +1,62 @@ +# +# 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 LConcreteClass; +.super Ljava/lang/Object; +.implements LSuperInterface; +.implements LConflictInterface; + +# public class ConcreteClass implements SuperInterface, ConflictInterface { +# public String runReal() { +# return SuperInterface.super.runDefault(); +# } +# public String runConflict() { +# return ConflictInterface.super.runDefault(); +# } +# public String runDefault() { +# return "This is the wrong class to invoke"; +# } +# } + +.method public constructor <init>()V + .registers 1 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method public runConflict()Ljava/lang/String; +.registers 2 + # Do an invoke super on this class, to confuse runtime/compiler. + invoke-super {p0}, LConflictInterface;->runDefault()Ljava/lang/String; + move-result-object v0 + return-object v0 +.end method + + + +.method public runReal()Ljava/lang/String; +.registers 2 + # Do an invoke super on this class, to confuse runtime/compiler. + invoke-super {p0}, LSuperInterface;->runDefault()Ljava/lang/String; + move-result-object v0 + return-object v0 +.end method + +.method public runDefault()Ljava/lang/String; +.registers 2 + const-string v0, "This is the wrong class to invoke!" + return-object v0 +.end method diff --git a/test/972-iface-super-multidex/src/Main.java b/test/972-iface-super-multidex/src/Main.java new file mode 100644 index 0000000000..3fb3f45428 --- /dev/null +++ b/test/972-iface-super-multidex/src/Main.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +import java.lang.reflect.*; +public class Main { + public static void main(String[] args) { + Class<?> c = null; + try { + c = Class.forName("ConcreteClass"); + } catch (Exception e) { + System.out.println("Could not load class"); + e.printStackTrace(); + return; + } + try { + Method m = c.getMethod("runReal"); + System.out.println((String)m.invoke(c.newInstance(), new Object[0])); + } catch (Exception e) { + System.out.println("Unknown exception occurred"); + e.printStackTrace(); + } + try { + Method m = c.getMethod("runConflict"); + try { + System.out.println((String)m.invoke(c.newInstance(), new Object[0])); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } catch (AbstractMethodError e) { + System.out.println("Unexpected AME caught"); + e.printStackTrace(); + } catch (NoSuchMethodError e) { + System.out.println("Unexpected NSME caught"); + e.printStackTrace(); + } catch (IncompatibleClassChangeError e) { + System.out.println("Expected ICCE caught"); + } catch (Throwable e) { + System.out.println("Unknown exception caught!"); + e.printStackTrace(); + } + } +} diff --git a/test/973-default-multidex/expected.txt b/test/973-default-multidex/expected.txt new file mode 100644 index 0000000000..b376e81554 --- /dev/null +++ b/test/973-default-multidex/expected.txt @@ -0,0 +1 @@ +STRING!!!STRING!!! diff --git a/test/973-default-multidex/info.txt b/test/973-default-multidex/info.txt new file mode 100644 index 0000000000..17c0b7d279 --- /dev/null +++ b/test/973-default-multidex/info.txt @@ -0,0 +1,5 @@ +Smali-based tests for interface default methods. + +Obviously needs to run under ART or a Java 8 Language runtime and compiler. + +Tests that we handle referenced throws across dex files. diff --git a/test/973-default-multidex/smali-multidex/iface.smali b/test/973-default-multidex/smali-multidex/iface.smali new file mode 100644 index 0000000000..fa6d27f527 --- /dev/null +++ b/test/973-default-multidex/smali-multidex/iface.smali @@ -0,0 +1,40 @@ +# +# 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 abstract interface LIface; +.super Ljava/lang/Object; + +# public interface Iface { +# public default String getTwice() { +# return getString() + getString(); +# } +# public String getString(); +# } + +.method public getTwice()Ljava/lang/String; +.locals 2 + invoke-static {p0}, Ljava/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object; + invoke-interface {p0}, LIface;->getString()Ljava/lang/String; + move-result-object v0 + invoke-interface {p0}, LIface;->getString()Ljava/lang/String; + move-result-object v1 + invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String; + move-result-object v0 + return-object v0 +.end method + +.method public abstract getString()Ljava/lang/String; +.end method diff --git a/test/973-default-multidex/smali/concreteclass.smali b/test/973-default-multidex/smali/concreteclass.smali new file mode 100644 index 0000000000..e177f2698a --- /dev/null +++ b/test/973-default-multidex/smali/concreteclass.smali @@ -0,0 +1,47 @@ +# +# 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 LConcreteClass; +.super Ljava/lang/Object; +.implements LIface; + +# public class ConcreteClass implements Iface { +# public String getString() { +# return "STRING!!!"; +# } +# public String callMethod() { +# return this.getTwice(); +# } +# } + +.method public constructor <init>()V + .registers 1 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method public getString()Ljava/lang/String; +.registers 2 + const-string v0, "STRING!!!" + return-object v0 +.end method + +.method public callMethod()Ljava/lang/String; +.registers 2 + invoke-virtual {p0}, LConcreteClass;->getTwice()Ljava/lang/String; + move-result-object v0 + return-object v0 +.end method diff --git a/test/048-reflect-v8/src/IFaceA.java b/test/973-default-multidex/src/Main.java index 9b1f610f84..b93265a5b8 100644 --- a/test/048-reflect-v8/src/IFaceA.java +++ b/test/973-default-multidex/src/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * 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. @@ -14,11 +14,18 @@ * limitations under the License. */ -// Stored as a complex annotation Calendars(Calendar,Calendar) -// in the binary. -@Calendars ({ - @Calendar(dayOfMonth="if_a_first"), - @Calendar(dayOfMonth="if_b_last") -}) -public interface IFaceA { +import java.lang.reflect.*; +public class Main { + public static void main(String[] args) { + Class<?> c = null; + try { + c = Class.forName("ConcreteClass"); + Method m = c.getMethod("callMethod"); + System.out.println(m.invoke(c.newInstance(), new Object[0])); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("FAILED: Could not call method"); + return; + } + } } diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index bc60c3f6b6..dfb540edf2 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -445,7 +445,6 @@ TEST_ART_BROKEN_INTERPRETER_RUN_TESTS := # CFI unwinding expects managed frames, and the test does not iterate enough to even compile. JIT # also uses Generic JNI instead of the JNI compiler. TEST_ART_BROKEN_JIT_RUN_TESTS := \ - 566-polymorphic-inlining \ 137-cfi ifneq (,$(filter jit,$(COMPILER_TYPES))) @@ -548,10 +547,8 @@ TEST_ART_BROKEN_OPTIMIZING_READ_BARRIER_RUN_TESTS := \ 527-checker-array-access-split \ 537-checker-arraycopy -# Tests that should fail in the read barrier configuration with JIT. -# 496: Occasional timeout: "Fault message: timeout: the monitored command dumped core" (b/26786304). -TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS := \ - 496-checker-inlining-and-class-loader +# Tests that should fail in the read barrier configuration with JIT (Optimizing compiler). +TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS := ifeq ($(ART_USE_READ_BARRIER),true) ifneq (,$(filter interpreter,$(COMPILER_TYPES))) @@ -618,18 +615,6 @@ endif TEST_ART_BROKEN_DEFAULT_HEAP_POISONING_RUN_TESTS := TEST_ART_BROKEN_OPTIMIZING_HEAP_POISONING_RUN_TESTS := -# Tests broken by multi-image. -TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS := \ - 476-checker-ctor-memory-barrier \ - 530-checker-lse - -ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ - $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \ - $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), \ - $(TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS), $(ALL_ADDRESS_SIZES)) - -TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS := - # Clear variables ahead of appending to them when defining tests. $(foreach target, $(TARGET_TYPES), $(eval ART_RUN_TEST_$(call name-to-var,$(target))_RULES :=)) $(foreach target, $(TARGET_TYPES), \ diff --git a/test/etc/default-build b/test/etc/default-build index 7242428f1e..6e855ec30a 100755 --- a/test/etc/default-build +++ b/test/etc/default-build @@ -42,6 +42,12 @@ else HAS_SRC_MULTIDEX=false fi +if [ -d smali-multidex ]; then + HAS_SMALI_MULTIDEX=true +else + HAS_SMALI_MULTIDEX=false +fi + if [ -d src-ex ]; then HAS_SRC_EX=true else @@ -74,6 +80,9 @@ while true; do elif [ "x$1" = "x--no-src-multidex" ]; then HAS_SRC_MULTIDEX=false shift + elif [ "x$1" = "x--no-smali-multidex" ]; then + HAS_SMALI_MULTIDEX=false + shift elif [ "x$1" = "x--no-src-ex" ]; then HAS_SRC_EX=false shift @@ -171,6 +180,19 @@ if [ "${HAS_SMALI}" = "true" ]; then fi fi +if [ "${HAS_SMALI_MULTIDEX}" = "true" ]; then + # Compile Smali classes + ${SMALI} -JXmx512m ${SMALI_ARGS} --output smali_classes2.dex `find smali-multidex -name '*.smali'` + + # Don't bother with dexmerger if we provide our own main function in a smali file. + if [ ${HAS_SRC_MULTIDEX} = "true" ]; then + ${DXMERGER} classes2.dex classes2.dex smali_classes2.dex + else + mv smali_classes2.dex classes2.dex + fi +fi + + if [ ${HAS_SRC_EX} = "true" ]; then if [ ${USE_JACK} = "true" ]; then # Rename previous "classes.dex" so it is not overwritten. @@ -198,7 +220,7 @@ if [ ${HAS_SRC_EX} = "true" ]; then fi # Create a single jar with two dex files for multidex. -if [ ${HAS_SRC_MULTIDEX} = "true" ]; then +if [ ${HAS_SRC_MULTIDEX} = "true" ] || [ ${HAS_SMALI_MULTIDEX} = "true" ]; then zip $TEST_NAME.jar classes.dex classes2.dex elif [ ${NEED_DEX} = "true" ]; then zip $TEST_NAME.jar classes.dex |