# HG changeset patch # User amurillo # Date 1441751991 25200 # Node ID 54fbe836fcf0740ef104cbf1237e4757dd1caf4d # Parent 23b29549f8d12a7a6ffe2aba018e91b13b1b4f84# Parent 2050b3a0aadcb0e024bf798197421d58e54ec8bf Merge diff -r 23b29549f8d1 -r 54fbe836fcf0 .hgtags --- a/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ c25e882cee9622ec75c4e9d60633539a2f0a8809 jdk9-b77 c8753d0be1778944dc512ec86a459941ea1ad2c3 jdk9-b78 3966bd3b8167419aa05c6718a4af1cf54b1e3c58 jdk9-b79 +3c9f5bd909ae7187f24622ee4b69f8a5756a9271 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 .hgtags-top-repo --- a/.hgtags-top-repo Tue Sep 01 12:57:41 2015 +0300 +++ b/.hgtags-top-repo Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ 7972dc8f2a47f0c4cd8f02fa5662af41f028aa14 jdk9-b77 8c40d4143ee13bdf8170c68cc384c36ab1e9fadb jdk9-b78 ba08a9f79b9849716bae1f39f71333d47f604012 jdk9-b79 +f7c5ae2933c0b8510a420d1713a955e4ffc7ad0b jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 common/bin/logger.sh --- a/common/bin/logger.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/common/bin/logger.sh Tue Sep 08 15:39:51 2015 -0700 @@ -41,5 +41,19 @@ trap "rm -rf \"$RCDIR\"" EXIT LOGFILE=$1 shift + +# We need to handle command likes like "VAR1=val1 /usr/bin/cmd VAR2=val2". +# Do this by shifting away prepended variable assignments, and export them +# instead. +is_prefix=true +for opt; do + if [[ "$is_prefix" = true && "$opt" =~ ^.*=.*$ ]]; then + export $opt + shift + else + is_prefix=false + fi +done + (exec 3>&1 ; ("$@" 2>&1 1>&3; echo $? > "$RCDIR/rc") | tee -a $LOGFILE 1>&2 ; exec 3>&-) | tee -a $LOGFILE exit `cat "$RCDIR/rc"` diff -r 23b29549f8d1 -r 54fbe836fcf0 corba/.hgtags --- a/corba/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/corba/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ 8bb2441c0fec8b28f7bf11a0ca3ec1642e7ef457 jdk9-b77 182bb7accc5253bcfefd8edc1d4997ec8f9f8694 jdk9-b78 4ab250b8fac66ef8cd15ee78c40f0c651c96e16a jdk9-b79 +821a0373ef2d1642a9824facb938b901ad010413 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 hotspot/.hgtags --- a/hotspot/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/hotspot/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -482,3 +482,4 @@ e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77 20dc06b04fe5ec373879414d60ef82ac70faef98 jdk9-b78 e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79 +8e8377739c06b99b9011c003c77e0bef84c91e09 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 jaxp/.hgtags --- a/jaxp/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/jaxp/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ be357705874c4ba1a69c38fb211e5e31e35bf9cb jdk9-b77 5b1899c9822db4a80a29cac82af492afea9f8f41 jdk9-b78 cf809edc840ff7546677d38b13ebd8b3cae2bbda jdk9-b79 +f464f9b2fb1178f6a957e5730b4b5252c6149ed9 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 jaxws/.hgtags --- a/jaxws/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/jaxws/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -325,3 +325,4 @@ bd6ece68cf8aca34c8d992569892060c82cfd3f1 jdk9-b77 ac1748bab0743137574be3451307b6a6361719eb jdk9-b78 42ae657e0e104fa7877996b8095f2e3ab1596118 jdk9-b79 +e9940bf1c8ddaa6f1f5f1813846b080f0ccaf50b jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/.hgtags --- a/jdk/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ 7fd081100f48828431e7c1bff65c906ee759069b jdk9-b77 0940ce86c614458f5bdd72278b190abbf36b7b45 jdk9-b78 d99c2ffdd0f15753e69126583688f2f075a0a5e8 jdk9-b79 +4947810137ae53abba3028cc366af953d90fa81a jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/README --- a/jdk/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/README Tue Sep 08 15:39:51 2015 -0700 @@ -25,5 +25,3 @@ 5. Construct the images: cd make && gnumake images The resulting JDK image should be found in build/*/j2sdk-image - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/lib/Awt2dLibraries.gmk --- a/jdk/make/lib/Awt2dLibraries.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/lib/Awt2dLibraries.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -887,7 +887,8 @@ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS), \ DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result maybe-uninitialized, \ DISABLED_WARNINGS_clang := incompatible-pointer-types, \ - DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE, \ + DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE \ + E_STATEMENT_NOT_REACHED, \ DISABLED_WARNINGS_microsoft := 4018 4244 4267, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsplashscreen/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/lib/CoreLibraries.gmk --- a/jdk/make/lib/CoreLibraries.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/lib/CoreLibraries.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -146,6 +146,7 @@ OPTIMIZATION := HIGH, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(LIBJAVA_CFLAGS), \ + DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ @@ -307,7 +308,9 @@ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ CFLAGS := $(LIBJLI_CFLAGS), \ - DISABLED_WARNINGS_solstudio := E_ASM_DISABLES_OPTIMIZATION, \ + DISABLED_WARNINGS_solstudio := \ + E_ASM_DISABLES_OPTIMIZATION \ + E_STATEMENT_NOT_REACHED, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjli/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/lib/NetworkingLibraries.gmk --- a/jdk/make/lib/NetworkingLibraries.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/lib/NetworkingLibraries.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -35,6 +35,7 @@ DISABLED_WARNINGS_gcc := format-nonliteral, \ DISABLED_WARNINGS_clang := parentheses-equality constant-logical-operand, \ DISABLED_WARNINGS_microsoft := 4244 4047 4133 4996, \ + DISABLED_WARNINGS_solstudio := E_ARG_INCOMPATIBLE_WITH_ARG_L, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/lib/NioLibraries.gmk --- a/jdk/make/lib/NioLibraries.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/lib/NioLibraries.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -47,7 +47,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) BUILD_LIBNIO_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnio/mapfile-$(OPENJDK_TARGET_OS) BUILD_LIBNIO_EXFILES += \ - GnomeFileTypeDetector.c \ + GioFileTypeDetector.c \ # endif diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/mapfiles/libnio/mapfile-linux --- a/jdk/make/mapfiles/libnio/mapfile-linux Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/mapfiles/libnio/mapfile-linux Tue Sep 08 15:39:51 2015 -0700 @@ -135,8 +135,8 @@ Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; - Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio; - Java_sun_nio_fs_GnomeFileTypeDetector_probeGio; + Java_sun_nio_fs_GioFileTypeDetector_initializeGio; + Java_sun_nio_fs_GioFileTypeDetector_probeGio; Java_sun_nio_fs_MagicFileTypeDetector_initialize0; Java_sun_nio_fs_MagicFileTypeDetector_probe0; Java_sun_nio_fs_LinuxWatchService_eventSize; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/mapfiles/libnio/mapfile-solaris --- a/jdk/make/mapfiles/libnio/mapfile-solaris Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/mapfiles/libnio/mapfile-solaris Tue Sep 08 15:39:51 2015 -0700 @@ -130,8 +130,8 @@ Java_sun_nio_ch_SolarisEventPort_port_1get; Java_sun_nio_ch_SolarisEventPort_port_1getn; Java_sun_nio_ch_SolarisEventPort_port_1send; - Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio; - Java_sun_nio_fs_GnomeFileTypeDetector_probeGio; + Java_sun_nio_fs_GioFileTypeDetector_initializeGio; + Java_sun_nio_fs_GioFileTypeDetector_probeGio; Java_sun_nio_fs_UnixNativeDispatcher_init; Java_sun_nio_fs_UnixNativeDispatcher_getcwd; Java_sun_nio_fs_UnixNativeDispatcher_strerror; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/make/netbeans/jdbc/build.properties --- a/jdk/make/netbeans/jdbc/build.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/make/netbeans/jdbc/build.properties Tue Sep 08 15:39:51 2015 -0700 @@ -43,4 +43,4 @@ build.number = b00 jdbc.version = ${build.release}-${user.name}-${build.number} jdbc.args = -debug -javadoc.options=-J-Xmx256m -Xdoclint:none -keywords -quiet \ No newline at end of file +javadoc.options=-J-Xmx256m -Xdoclint:none -keywords -quiet diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/demo/share/applets/Fractal/example1.html --- a/jdk/src/demo/share/applets/Fractal/example1.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/demo/share/applets/Fractal/example1.html Tue Sep 08 15:39:51 2015 -0700 @@ -23,5 +23,3 @@ The source. - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/demo/share/applets/MoleculeViewer/example1.html --- a/jdk/src/demo/share/applets/MoleculeViewer/example1.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/demo/share/applets/MoleculeViewer/example1.html Tue Sep 08 15:39:51 2015 -0700 @@ -14,9 +14,3 @@ The source. - - - - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,7 @@ new GetPropertyAction("user.home")), ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); - return chain(new GnomeFileTypeDetector(), + return chain(new GioFileTypeDetector(), new MimeTypesFileTypeDetector(userMimeTypes), new MimeTypesFileTypeDetector(etcMimeTypes), new MagicFileTypeDetector()); diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/share/classes/java/security/KeyStore.java --- a/jdk/src/java.base/share/classes/java/security/KeyStore.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java Tue Sep 08 15:39:51 2015 -0700 @@ -1611,8 +1611,13 @@ * First the keystore type is determined by probing the specified file. * Then a keystore object is instantiated and loaded using the data from * that file. - * A password may be supplied to unlock the keystore data or perform an - * integrity check. + * + *

+ * A password may be given to unlock the keystore + * (e.g. the keystore resides on a hardware token device), + * or to check the integrity of the keystore data. + * If a password is not given for integrity checking, + * then integrity checking is not performed. * *

* This method traverses the list of registered security diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties --- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Tue Sep 08 15:39:51 2015 -0700 @@ -60,8 +60,8 @@ \ -dsa | -disablesystemassertions\n\ \ disable system assertions\n\ \ -agentlib:[=]\n\ -\ load native agent library , e.g. -agentlib:hprof\n\ -\ see also, -agentlib:jdwp=help and -agentlib:hprof=help\n\ +\ load native agent library , e.g. -agentlib:jdwp\n\ +\ see also -agentlib:jdwp=help\n\ \ -agentpath:[=]\n\ \ load native agent library by full pathname\n\ \ -javaagent:[=]\n\ diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/share/native/libzip/Adler32.c --- a/jdk/src/java.base/share/native/libzip/Adler32.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/share/native/libzip/Adler32.c Tue Sep 08 15:39:51 2015 -0700 @@ -66,5 +66,3 @@ } return adler; } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,7 @@ new GetPropertyAction("user.home")), ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); - return chain(new GnomeFileTypeDetector(), + return chain(new GioFileTypeDetector(), new MimeTypesFileTypeDetector(userMimeTypes), new MimeTypesFileTypeDetector(etcMimeTypes)); } diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/classes/sun/net/www/content-types.properties --- a/jdk/src/java.base/unix/classes/sun/net/www/content-types.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/unix/classes/sun/net/www/content-types.properties Tue Sep 08 15:39:51 2015 -0700 @@ -275,6 +275,3 @@ application/xml: \ description=XML document;\ file_extensions=.xml - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/classes/sun/nio/fs/GioFileTypeDetector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/GioFileTypeDetector.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.fs; + +import java.nio.file.Path; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * File type detector that uses the GNOME I/O library to guess the + * MIME type of a file. + */ + +public class GioFileTypeDetector + extends AbstractFileTypeDetector +{ + // true if GIO is available + private final boolean gioAvailable; + + public GioFileTypeDetector() { + gioAvailable = initializeGio(); + } + + @Override + public String implProbeContentType(Path obj) throws IOException { + if (!gioAvailable) + return null; + if (!(obj instanceof UnixPath)) + return null; + + UnixPath path = (UnixPath)obj; + NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls()); + try { + // GIO may access file so need permission check + path.checkRead(); + byte[] type = probeGio(buffer.address()); + return (type == null) ? null : Util.toString(type); + } finally { + buffer.release(); + } + + } + + // GIO + private static native boolean initializeGio(); + // + // The probeGIO() method is synchronized to avert potential problems + // such as crashes due to a suspected lack of thread safety in GIO. + // + private static synchronized native byte[] probeGio(long pathAddress); + + static { + AccessController.doPrivileged(new PrivilegedAction<>() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/classes/sun/nio/fs/GnomeFileTypeDetector.java --- a/jdk/src/java.base/unix/classes/sun/nio/fs/GnomeFileTypeDetector.java Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.fs; - -import java.nio.file.Path; -import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * File type detector that uses the GNOME I/O library to guess the - * MIME type of a file. - */ - -public class GnomeFileTypeDetector - extends AbstractFileTypeDetector -{ - // true if GIO is available - private final boolean gioAvailable; - - public GnomeFileTypeDetector() { - gioAvailable = initializeGio(); - } - - @Override - public String implProbeContentType(Path obj) throws IOException { - if (!gioAvailable) - return null; - if (!(obj instanceof UnixPath)) - return null; - - UnixPath path = (UnixPath)obj; - NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls()); - try { - // GIO may access file so need permission check - path.checkRead(); - byte[] type = probeGio(buffer.address()); - return (type == null) ? null : Util.toString(type); - } finally { - buffer.release(); - } - - } - - // GIO - private static native boolean initializeGio(); - private static synchronized native byte[] probeGio(long pathAddress); - - static { - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - System.loadLibrary("nio"); - return null; - }}); - } -} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c --- a/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Tue Sep 08 15:39:51 2015 -0700 @@ -26,9 +26,11 @@ #include #include +#include "jni.h" +#include "jni_util.h" #include "jvm.h" + #include "io_util_md.h" - #include "java_io_FileDescriptor.h" /*******************************************************************/ @@ -47,8 +49,8 @@ JNIEXPORT void JNICALL Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) { - IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I"); - IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z"); + CHECK_NULL(IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I")); + CHECK_NULL(IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z")); } /************************************************************** diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/native/libnio/fs/GioFileTypeDetector.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/unix/native/libnio/fs/GioFileTypeDetector.c Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include + +#ifdef __solaris__ +#include +#endif + +#if defined(__linux__) +#include +#endif + +/* + * For reference see for example the GFileInfo section at + * https://developer.gnome.org/gio/unstable/. + */ + +/* Definitions for GIO */ + +#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type" + +typedef void* gpointer; +typedef struct _GFile GFile; +typedef struct _GFileInfo GFileInfo; +typedef struct _GCancellable GCancellable; +typedef struct _GError GError; + +typedef enum { + G_FILE_QUERY_INFO_NONE = 0 +} GFileQueryInfoFlags; + +typedef void (*g_type_init_func)(void); +typedef void (*g_object_unref_func)(gpointer object); +typedef GFile* (*g_file_new_for_path_func)(const char* path); +typedef GFileInfo* (*g_file_query_info_func)(GFile *file, + const char *attributes, GFileQueryInfoFlags flags, + GCancellable *cancellable, GError **error); +typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info); + +static g_type_init_func g_type_init; +static g_object_unref_func g_object_unref; +static g_file_new_for_path_func g_file_new_for_path; +static g_file_query_info_func g_file_query_info; +static g_file_info_get_content_type_func g_file_info_get_content_type; + + +#include "sun_nio_fs_GioFileTypeDetector.h" + + +JNIEXPORT jboolean JNICALL +Java_sun_nio_fs_GioFileTypeDetector_initializeGio + (JNIEnv* env, jclass this) +{ + void* gio_handle; + + gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY); + if (gio_handle == NULL) { + gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY); + if (gio_handle == NULL) { + return JNI_FALSE; + } + } + + g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init"); + (*g_type_init)(); + + g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref"); + + g_file_new_for_path = + (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path"); + + g_file_query_info = + (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info"); + + g_file_info_get_content_type = (g_file_info_get_content_type_func) + dlsym(gio_handle, "g_file_info_get_content_type"); + + + if (g_type_init == NULL || + g_object_unref == NULL || + g_file_new_for_path == NULL || + g_file_query_info == NULL || + g_file_info_get_content_type == NULL) + { + dlclose(gio_handle); + return JNI_FALSE; + } + + (*g_type_init)(); + return JNI_TRUE; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_GioFileTypeDetector_probeGio + (JNIEnv* env, jclass this, jlong pathAddress) +{ + char* path = (char*)jlong_to_ptr(pathAddress); + GFile* gfile; + GFileInfo* gfileinfo; + jbyteArray result = NULL; + + gfile = (*g_file_new_for_path)(path); + gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (gfileinfo != NULL) { + const char* mime = (*g_file_info_get_content_type)(gfileinfo); + if (mime != NULL) { + jsize len = strlen(mime); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime); + } + } + (*g_object_unref)(gfileinfo); + } + (*g_object_unref)(gfile); + + return result; +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/unix/native/libnio/fs/GnomeFileTypeDetector.c --- a/jdk/src/java.base/unix/native/libnio/fs/GnomeFileTypeDetector.c Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jvm.h" -#include "jlong.h" - -#include -#include - -#ifdef __solaris__ -#include -#endif - -#if defined(__linux__) -#include -#endif - -/* - * For reference see for example the GFileInfo section at - * https://developer.gnome.org/gio/unstable/. - */ - -/* Definitions for GIO */ - -#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type" - -typedef void* gpointer; -typedef struct _GFile GFile; -typedef struct _GFileInfo GFileInfo; -typedef struct _GCancellable GCancellable; -typedef struct _GError GError; - -typedef enum { - G_FILE_QUERY_INFO_NONE = 0 -} GFileQueryInfoFlags; - -typedef void (*g_type_init_func)(void); -typedef void (*g_object_unref_func)(gpointer object); -typedef GFile* (*g_file_new_for_path_func)(const char* path); -typedef GFileInfo* (*g_file_query_info_func)(GFile *file, - const char *attributes, GFileQueryInfoFlags flags, - GCancellable *cancellable, GError **error); -typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info); - -static g_type_init_func g_type_init; -static g_object_unref_func g_object_unref; -static g_file_new_for_path_func g_file_new_for_path; -static g_file_query_info_func g_file_query_info; -static g_file_info_get_content_type_func g_file_info_get_content_type; - - -#include "sun_nio_fs_GnomeFileTypeDetector.h" - - -JNIEXPORT jboolean JNICALL -Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio - (JNIEnv* env, jclass this) -{ - void* gio_handle; - - gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY); - if (gio_handle == NULL) { - gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY); - if (gio_handle == NULL) { - return JNI_FALSE; - } - } - - g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init"); - (*g_type_init)(); - - g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref"); - - g_file_new_for_path = - (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path"); - - g_file_query_info = - (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info"); - - g_file_info_get_content_type = (g_file_info_get_content_type_func) - dlsym(gio_handle, "g_file_info_get_content_type"); - - - if (g_type_init == NULL || - g_object_unref == NULL || - g_file_new_for_path == NULL || - g_file_query_info == NULL || - g_file_info_get_content_type == NULL) - { - dlclose(gio_handle); - return JNI_FALSE; - } - - (*g_type_init)(); - return JNI_TRUE; -} - -JNIEXPORT jbyteArray JNICALL -Java_sun_nio_fs_GnomeFileTypeDetector_probeGio - (JNIEnv* env, jclass this, jlong pathAddress) -{ - char* path = (char*)jlong_to_ptr(pathAddress); - GFile* gfile; - GFileInfo* gfileinfo; - jbyteArray result = NULL; - - gfile = (*g_file_new_for_path)(path); - gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, NULL, NULL); - if (gfileinfo != NULL) { - const char* mime = (*g_file_info_get_content_type)(gfileinfo); - if (mime != NULL) { - jsize len = strlen(mime); - result = (*env)->NewByteArray(env, len); - if (result != NULL) { - (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime); - } - } - (*g_object_unref)(gfileinfo); - } - (*g_object_unref)(gfile); - - return result; -} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.base/windows/classes/sun/net/www/content-types.properties --- a/jdk/src/java.base/windows/classes/sun/net/www/content-types.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.base/windows/classes/sun/net/www/content-types.properties Tue Sep 08 15:39:51 2015 -0700 @@ -272,5 +272,3 @@ application/xml: \ description=XML document;\ file_extensions=.xml - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/macosx/classes/com/apple/eawt/_OpenAppHandler.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_OpenAppHandler.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_OpenAppHandler.java Tue Sep 08 15:39:51 2015 -0700 @@ -27,4 +27,4 @@ interface _OpenAppHandler { void handleOpenApp(); -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Tue Sep 08 15:39:51 2015 -0700 @@ -1098,4 +1098,4 @@ }; table.putDefaults(uiDefaults); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Tue Sep 08 15:39:51 2015 -0700 @@ -278,5 +278,3 @@ return false; } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Tue Sep 08 15:39:51 2015 -0700 @@ -1406,5 +1406,3 @@ return underMouse; } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m Tue Sep 08 15:39:51 2015 -0700 @@ -289,4 +289,4 @@ JNF_COCOA_EXIT(env); return ret; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/classes/sun/awt/image/MultiResolutionCachedImage.java --- a/jdk/src/java.desktop/share/classes/sun/awt/image/MultiResolutionCachedImage.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/MultiResolutionCachedImage.java Tue Sep 08 15:39:51 2015 -0700 @@ -183,4 +183,4 @@ return false; } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/AnchorTables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/AnchorTables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/AnchorTables.h Tue Sep 08 15:39:51 2015 -0700 @@ -80,5 +80,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/CharSubstitutionFilter.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/CharSubstitutionFilter.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/CharSubstitutionFilter.h Tue Sep 08 15:39:51 2015 -0700 @@ -104,5 +104,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.h Tue Sep 08 15:39:51 2015 -0700 @@ -63,5 +63,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.h Tue Sep 08 15:39:51 2015 -0700 @@ -61,5 +61,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/MPreFixups.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/MPreFixups.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/MPreFixups.h Tue Sep 08 15:39:51 2015 -0700 @@ -63,5 +63,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/MarkArrays.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/MarkArrays.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/MarkArrays.h Tue Sep 08 15:39:51 2015 -0700 @@ -62,5 +62,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/PairPositioningSubtables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/PairPositioningSubtables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/PairPositioningSubtables.h Tue Sep 08 15:39:51 2015 -0700 @@ -109,5 +109,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/SinglePositioningSubtables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/SinglePositioningSubtables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/SinglePositioningSubtables.h Tue Sep 08 15:39:51 2015 -0700 @@ -71,5 +71,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/SingleSubstitutionSubtables.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/SingleSubstitutionSubtables.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/SingleSubstitutionSubtables.h Tue Sep 08 15:39:51 2015 -0700 @@ -68,5 +68,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Tue Sep 08 15:39:51 2015 -0700 @@ -129,5 +129,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libfontmanager/layout/ValueRecords.h --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ValueRecords.h Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ValueRecords.h Tue Sep 08 15:39:51 2015 -0700 @@ -94,5 +94,3 @@ U_NAMESPACE_END #endif - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/liblcms/cmslut.c --- a/jdk/src/java.desktop/share/native/liblcms/cmslut.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/liblcms/cmslut.c Tue Sep 08 15:39:51 2015 -0700 @@ -1836,5 +1836,3 @@ return TRUE; } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/liblcms/cmsmtrx.c --- a/jdk/src/java.desktop/share/native/liblcms/cmsmtrx.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/liblcms/cmsmtrx.c Tue Sep 08 15:39:51 2015 -0700 @@ -201,5 +201,3 @@ r->n[VY] = a->v[1].n[VX]*v->n[VX] + a->v[1].n[VY]*v->n[VY] + a->v[1].n[VZ]*v->n[VZ]; r->n[VZ] = a->v[2].n[VX]*v->n[VX] + a->v[2].n[VY]*v->n[VY] + a->v[2].n[VZ]*v->n[VZ]; } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/liblcms/cmsplugin.c --- a/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Tue Sep 08 15:39:51 2015 -0700 @@ -989,5 +989,3 @@ { return _cmsContextGetClientChunk(ContextID, UserPtr); } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c --- a/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Tue Sep 08 15:39:51 2015 -0700 @@ -376,5 +376,3 @@ return TRUE; } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c --- a/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c Tue Sep 08 15:39:51 2015 -0700 @@ -234,4 +234,4 @@ return 1; } return splash->scaleFactor; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/windows/native/libawt/windows/DllUtil.cpp --- a/jdk/src/java.desktop/windows/native/libawt/windows/DllUtil.cpp Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/windows/native/libawt/windows/DllUtil.cpp Tue Sep 08 15:39:51 2015 -0700 @@ -84,5 +84,3 @@ } throw FunctionUnavailableException(); } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.desktop/windows/native/libawt/windows/README.JNI --- a/jdk/src/java.desktop/windows/native/libawt/windows/README.JNI Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.desktop/windows/native/libawt/windows/README.JNI Tue Sep 08 15:39:51 2015 -0700 @@ -131,5 +131,3 @@ 2. Handle exceptions properly. The current code lacks error checking and recovery. This leads to random runtime crashes. - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.logging/share/classes/java/util/logging/package.html --- a/jdk/src/java.logging/share/classes/java/util/logging/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.logging/share/classes/java/util/logging/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -126,8 +126,3 @@ - - - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.management/share/classes/javax/management/ObjectName.java --- a/jdk/src/java.management/share/classes/javax/management/ObjectName.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.management/share/classes/javax/management/ObjectName.java Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,9 +218,19 @@ *

The serialVersionUID of this class is 1081892073854801359L. * * @since 1.5 + * + * @implNote The maximum allowed length of the domain name in this implementation + * is {@code Integer.MAX_VALUE/4} */ @SuppressWarnings("serial") // don't complain serialVersionUID not constant public class ObjectName implements Comparable, QueryExp { + private static final int DOMAIN_PATTERN = 0x8000_0000; + private static final int PROPLIST_PATTERN = 0x4000_0000; + private static final int PROPVAL_PATTERN = 0x2000_0000; + + private static final int FLAG_MASK = DOMAIN_PATTERN | PROPLIST_PATTERN | + PROPVAL_PATTERN; + private static final int DOMAIN_LENGTH_MASK = ~FLAG_MASK; /** * A structure recording property structure and @@ -365,33 +375,25 @@ /** - * The length of the domain part of built objectname - */ - private transient int _domain_length = 0; - - - /** * The propertyList of built object name. Initialized lazily. * Table that contains all the pairs (key,value) for this ObjectName. */ private transient Map _propertyList; /** - * boolean that declares if this ObjectName domain part is a pattern - */ - private transient boolean _domain_pattern = false; - - /** - * boolean that declares if this ObjectName contains a pattern on the - * key property list + * This field encodes _domain_pattern, _property_list_pattern and + * _property_value_pattern booleans and _domain_length integer. + *

+ * The following masks can be used to extract the value: + *

+ *

. */ - private transient boolean _property_list_pattern = false; - - /** - * boolean that declares if this ObjectName contains a pattern on the - * value of at least one key property - */ - private transient boolean _property_value_pattern = false; + private transient int _compressed_storage = 0x0; // Instance private fields <======================================= @@ -426,11 +428,11 @@ _canonicalName = "*:*"; _kp_array = _Empty_property_array; _ca_array = _Empty_property_array; - _domain_length = 1; + setDomainLength(1); _propertyList = null; - _domain_pattern = true; - _property_list_pattern = true; - _property_value_pattern = false; + setDomainPattern(true); + setPropertyListPattern(true); + setPropertyValuePattern(false); return; } @@ -448,7 +450,7 @@ while (index < len) { switch (name_chars[index]) { case ':' : - _domain_length = index++; + setDomainLength(index++); break domain_parsing; case '=' : // ":" omission check. @@ -469,7 +471,7 @@ "Invalid character '\\n' in domain name"); case '*' : case '?' : - _domain_pattern = true; + setDomainPattern(true); index++; break; default : @@ -484,6 +486,7 @@ "Key properties cannot be empty"); // we have got the domain part, begins building of _canonicalName + int _domain_length = getDomainLength(); System.arraycopy(name_chars, 0, canonical_chars, 0, _domain_length); canonical_chars[_domain_length] = ':'; cname_index = _domain_length + 1; @@ -500,20 +503,20 @@ keys = new String[10]; _kp_array = new Property[10]; - _property_list_pattern = false; - _property_value_pattern = false; + setPropertyListPattern(false); + setPropertyValuePattern(false); while (index < len) { c = name_chars[index]; // case of pattern properties if (c == '*') { - if (_property_list_pattern) + if (isPropertyListPattern()) throw new MalformedObjectNameException( "Cannot have several '*' characters in pattern " + "property list"); else { - _property_list_pattern = true; + setPropertyListPattern(true); if ((++index < len ) && (name_chars[index] != ',')) throw new MalformedObjectNameException( "Invalid character found after '*': end of " + @@ -639,7 +642,7 @@ if (!value_pattern) { prop = new Property(key_index, key_length, value_length); } else { - _property_value_pattern = true; + setPropertyValuePattern(true); prop = new PatternProperty(key_index, key_length, value_length); } key_name = name.substring(key_index, key_index + key_length); @@ -670,7 +673,8 @@ * @exception MalformedObjectNameException The domain * contains an illegal character, or one of the keys or values in * table contains an illegal character, or one of the - * values in table does not follow the rules for quoting. + * values in table does not follow the rules for quoting, + * or the domain's length exceeds the maximum allowed length. * @exception NullPointerException One of the parameters is null. */ private void construct(String domain, Map props) @@ -696,7 +700,7 @@ // init canonicalname final StringBuilder sb = new StringBuilder(); sb.append(domain).append(':'); - _domain_length = domain.length(); + setDomainLength(domain.length()); // allocates the property array int nb_props = props.size(); @@ -729,7 +733,7 @@ key.length(), value.length()); } else { - _property_value_pattern = true; + setPropertyValuePattern(true); prop = new PatternProperty(key_index, key.length(), value.length()); @@ -743,10 +747,10 @@ char[] initial_chars = new char[len]; sb.getChars(0, len, initial_chars, 0); char[] canonical_chars = new char[len]; - System.arraycopy(initial_chars, 0, canonical_chars, 0, - _domain_length + 1); + int copyLen = getDomainLength() + 1; + System.arraycopy(initial_chars, 0, canonical_chars, 0, copyLen); setCanonicalName(initial_chars, canonical_chars, keys, keys_map, - _domain_length + 1, _kp_array.length); + copyLen, _kp_array.length); } // Category : Instance construction <============================== @@ -822,7 +826,7 @@ } // terminate canonicalname with '*' in case of pattern - if (_property_list_pattern) { + if (isPropertyListPattern()) { if (_kp_array != _Empty_property_array) canonical_chars[prop_index++] = ','; canonical_chars[prop_index++] = '*'; @@ -1051,13 +1055,32 @@ return false; case '*' : case '?' : - _domain_pattern = true; + setDomainPattern(true); break; } } return true; } + private int getDomainLength() { + return _compressed_storage & DOMAIN_LENGTH_MASK; + } + + /** + * Validates and sets the domain length + * @param length The domain length + * @throws MalformedObjectNameException + * When the given domain length exceeds the maximum allowed length + */ + private void setDomainLength(int length) throws MalformedObjectNameException { + if ((length & FLAG_MASK) != 0 ) { + throw new MalformedObjectNameException( + "Domain name too long. Maximum allowed domain name length is:" + + DOMAIN_LENGTH_MASK); + } + _compressed_storage = (_compressed_storage & FLAG_MASK) | length; + } + // Category : Internal accessors <============================== // Category : Serialization -----------------------------------> @@ -1225,12 +1248,12 @@ // Serializes this instance in the old serial form // Read CR 6441274 before making any changes to this code ObjectOutputStream.PutField fields = out.putFields(); - fields.put("domain", _canonicalName.substring(0, _domain_length)); + fields.put("domain", _canonicalName.substring(0, getDomainLength())); fields.put("propertyList", getKeyPropertyList()); fields.put("propertyListString", getKeyPropertyListString()); fields.put("canonicalName", _canonicalName); - fields.put("pattern", (_domain_pattern || _property_list_pattern)); - fields.put("propertyPattern", _property_list_pattern); + fields.put("pattern", (_compressed_storage & (DOMAIN_PATTERN | PROPLIST_PATTERN)) != 0); + fields.put("propertyPattern", isPropertyListPattern()); out.writeFields(); } else @@ -1291,7 +1314,8 @@ * @exception MalformedObjectNameException The * domain, key, or value * contains an illegal character, or value does not - * follow the rules for quoting. + * follow the rules for quoting, or the domain's length exceeds + * the maximum allowed length. * @exception NullPointerException One of the parameters is null. * */ @@ -1322,7 +1346,7 @@ * contains an illegal character, or one of the keys or values in * table contains an illegal character, or one of the * values in table does not follow the rules for - * quoting. + * quoting, or the domain's length exceeds the maximum allowed length. * @exception NullPointerException One of the parameters is null. * */ @@ -1392,7 +1416,8 @@ * @exception MalformedObjectNameException The * domain, key, or value * contains an illegal character, or value does not - * follow the rules for quoting. + * follow the rules for quoting, or the domain's length exceeds + * the maximum allowed length. * @exception NullPointerException One of the parameters is null. */ public ObjectName(String domain, String key, String value) @@ -1417,7 +1442,7 @@ * contains an illegal character, or one of the keys or values in * table contains an illegal character, or one of the * values in table does not follow the rules for - * quoting. + * quoting, or the domain's length exceeds the maximum allowed length. * @exception NullPointerException One of the parameters is null. */ public ObjectName(String domain, Hashtable table) @@ -1443,9 +1468,7 @@ * @return True if the name is a pattern, otherwise false. */ public boolean isPattern() { - return (_domain_pattern || - _property_list_pattern || - _property_value_pattern); + return (_compressed_storage & FLAG_MASK) != 0; } /** @@ -1455,7 +1478,20 @@ * */ public boolean isDomainPattern() { - return _domain_pattern; + return (_compressed_storage & DOMAIN_PATTERN) != 0; + } + + /** + * Marks the object name as representing a pattern on the domain part. + * @param value {@code true} if the domain name is a pattern, + * {@code false} otherwise + */ + private void setDomainPattern(boolean value) { + if (value) { + _compressed_storage |= DOMAIN_PATTERN; + } else { + _compressed_storage &= ~DOMAIN_PATTERN; + } } /** @@ -1468,7 +1504,7 @@ * @return True if the name is a property pattern, otherwise false. */ public boolean isPropertyPattern() { - return _property_list_pattern || _property_value_pattern; + return (_compressed_storage & (PROPVAL_PATTERN | PROPLIST_PATTERN)) != 0; } /** @@ -1482,7 +1518,20 @@ * @since 1.6 */ public boolean isPropertyListPattern() { - return _property_list_pattern; + return (_compressed_storage & PROPLIST_PATTERN) != 0; + } + + /** + * Marks the object name as representing a pattern on the key property list. + * @param value {@code true} if the key property list is a pattern, + * {@code false} otherwise + */ + private void setPropertyListPattern(boolean value) { + if (value) { + _compressed_storage |= PROPLIST_PATTERN; + } else { + _compressed_storage &= ~PROPLIST_PATTERN; + } } /** @@ -1497,7 +1546,20 @@ * @since 1.6 */ public boolean isPropertyValuePattern() { - return _property_value_pattern; + return (_compressed_storage & PROPVAL_PATTERN) != 0; + } + + /** + * Marks the object name as representing a pattern on the value part. + * @param value {@code true} if the value part of at least one of the + * key properties is a pattern, {@code false} otherwise + */ + private void setPropertyValuePattern(boolean value) { + if (value) { + _compressed_storage |= PROPVAL_PATTERN; + } else { + _compressed_storage &= ~PROPVAL_PATTERN; + } } /** @@ -1563,7 +1625,7 @@ * @return The domain. */ public String getDomain() { - return _canonicalName.substring(0, _domain_length); + return _canonicalName.substring(0, getDomainLength()); } /** @@ -1640,8 +1702,8 @@ // the size of the string is the canonical one minus domain // part and pattern part - final int total_size = _canonicalName.length() - _domain_length - 1 - - (_property_list_pattern?2:0); + final int total_size = _canonicalName.length() - getDomainLength() - 1 + - (isPropertyListPattern()?2:0); final char[] dest_chars = new char[total_size]; final char[] value = _canonicalName.toCharArray(); @@ -1665,7 +1727,7 @@ final int total_size = _canonicalName.length(); final char[] dest_chars = new char[total_size]; final char[] value = _canonicalName.toCharArray(); - final int offset = _domain_length+1; + final int offset = getDomainLength() + 1; // copy "domain:" into dest_chars // @@ -1675,7 +1737,7 @@ final int end = writeKeyPropertyListString(value,dest_chars,offset); // Add ",*" if necessary - if (_property_list_pattern) { + if (isPropertyListPattern()) { if (end == offset) { // Property list string is empty. dest_chars[end] = '*'; @@ -1737,8 +1799,8 @@ if (_ca_array.length == 0) return ""; int len = _canonicalName.length(); - if (_property_list_pattern) len -= 2; - return _canonicalName.substring(_domain_length +1, len); + if (isPropertyListPattern()) len -= 2; + return _canonicalName.substring(getDomainLength() + 1, len); } // Category : Getter methods <=================================== @@ -1944,22 +2006,18 @@ if (name == null) throw new NullPointerException(); - if (name._domain_pattern || - name._property_list_pattern || - name._property_value_pattern) + if (name.isPattern()) return false; // No pattern - if (!_domain_pattern && - !_property_list_pattern && - !_property_value_pattern) + if (!isPattern()) return _canonicalName.equals(name._canonicalName); return matchDomains(name) && matchKeys(name); } private final boolean matchDomains(ObjectName name) { - if (_domain_pattern) { + if (isDomainPattern()) { // wildmatch domains // This ObjectName is the pattern // The other ObjectName is the string. @@ -1972,15 +2030,15 @@ // If key property value pattern but not key property list // pattern, then the number of key properties must be equal // - if (_property_value_pattern && - !_property_list_pattern && + if (isPropertyValuePattern() && + !isPropertyListPattern() && (name._ca_array.length != _ca_array.length)) return false; // If key property value pattern or key property list pattern, // then every property inside pattern should exist in name // - if (_property_value_pattern || _property_list_pattern) { + if (isPropertyPattern()) { final Map nameProps = name._getKeyPropertyList(); final Property[] props = _ca_array; final String cn = _canonicalName; @@ -1996,7 +2054,7 @@ if (v == null) return false; // If this property is ok (same key, same value), go to next // - if (_property_value_pattern && (p instanceof PatternProperty)) { + if (isPropertyValuePattern() && (p instanceof PatternProperty)) { // wildmatch key property values // p is the property pattern, v is the string if (Util.wildmatch(v,p.getValueString(cn))) diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Tue Sep 08 15:39:51 2015 -0700 @@ -132,7 +132,9 @@ * Checks if this Kerberos delegation permission object "implies" the * specified permission. *

- * If none of the above are true, {@code implies} returns false. + * This method returns true if this {@code DelegationPermission} + * is equal to {@code p}, and returns false otherwise. + * * @param p the permission to check against. * * @return true if the specified permission is implied by this object, diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Tue Sep 08 15:39:51 2015 -0700 @@ -179,7 +179,16 @@ * Checks if this Kerberos service permission object "implies" the * specified permission. *

- * If none of the above are true, {@code implies} returns false. + * More specifically, this method returns true if all of the following + * are true (and returns false if any of them are not): + *

    + *
  • p is an instanceof {@code ServicePermission}, + *
  • p's actions are a proper subset of this + * {@code ServicePermission}'s actions, + *
  • p's name is equal to this {@code ServicePermission}'s name + * or this {@code ServicePermission}'s name is "*". + *
+ * * @param p the permission to check against. * * @return true if the specified permission is implied by this object, diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Tue Sep 08 15:39:51 2015 -0700 @@ -4467,4 +4467,4 @@ static final long serialVersionUID = 4886719666485113312L; -} //end class \ No newline at end of file +} //end class diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetFactory.java --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetFactory.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetFactory.java Tue Sep 08 15:39:51 2015 -0700 @@ -96,4 +96,4 @@ */ public WebRowSet createWebRowSet() throws SQLException; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

algorithm factories. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

basic handlers for elements that can occur inside ds:KeyValue. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

basic handlers for elements that can occur inside ds:KeyInfo. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

basic handlers for elements that can occur inside ds:X509Data. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

implementations for retrieval of certificates and public keys from elements. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

the resolver framework for retrieval of certificates and public keys from elements. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

implementations of resolvers for retrieval for certificates and public keys from user-specified locations. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/package.html --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/package.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/package.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@

a resolver framework for certificates and public keys from user-specified locations. -

\ No newline at end of file +

diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java Tue Sep 08 15:39:51 2015 -0700 @@ -24,4 +24,4 @@ package com.sun.org.apache.xml.internal.security.transforms; public interface TransformParam { -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c --- a/jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c Tue Sep 08 15:39:51 2015 -0700 @@ -77,14 +77,17 @@ static int get_totalticks(int which, ticks *pticks) { FILE *fh; uint64_t userTicks, niceTicks, systemTicks, idleTicks; + uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0; int n; if((fh = fopen("/proc/stat", "r")) == NULL) { return -1; } - n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, - &userTicks, &niceTicks, &systemTicks, &idleTicks); + n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " " + DEC_64 " " DEC_64, + &userTicks, &niceTicks, &systemTicks, &idleTicks, + &iowTicks, &irqTicks, &sirqTicks); // Move to next line next_line(fh); @@ -93,24 +96,30 @@ if (which != -1) { int i; for (i = 0; i < which; i++) { - if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) { + if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " " + DEC_64 " " DEC_64 " " DEC_64, + &userTicks, &niceTicks, &systemTicks, &idleTicks, + &iowTicks, &irqTicks, &sirqTicks) < 4) { fclose(fh); return -2; } next_line(fh); } - n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n", - &userTicks, &niceTicks, &systemTicks, &idleTicks); + n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " " + DEC_64 " " DEC_64 " " DEC_64 "\n", + &userTicks, &niceTicks, &systemTicks, &idleTicks, + &iowTicks, &irqTicks, &sirqTicks); } fclose(fh); - if (n != 4) { + if (n < 4) { return -2; } pticks->used = userTicks + niceTicks; - pticks->usedKernel = systemTicks; - pticks->total = userTicks + niceTicks + systemTicks + idleTicks; + pticks->usedKernel = systemTicks + irqTicks + sirqTicks; + pticks->total = userTicks + niceTicks + systemTicks + idleTicks + + iowTicks + irqTicks + sirqTicks; return 0; } diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/sample/share/annotations/DependencyChecker/PluginChecker/src/checker/Kettle.xml --- a/jdk/src/sample/share/annotations/DependencyChecker/PluginChecker/src/checker/Kettle.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/sample/share/annotations/DependencyChecker/PluginChecker/src/checker/Kettle.xml Tue Sep 08 15:39:51 2015 -0700 @@ -54,4 +54,4 @@ 4 - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/sample/share/annotations/index.html --- a/jdk/src/sample/share/annotations/index.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/sample/share/annotations/index.html Tue Sep 08 15:39:51 2015 -0700 @@ -64,4 +64,4 @@ Sources: Validator/src/ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/sample/share/lambda/BulkDataOperations/index.html --- a/jdk/src/sample/share/lambda/BulkDataOperations/index.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/sample/share/lambda/BulkDataOperations/index.html Tue Sep 08 15:39:51 2015 -0700 @@ -46,4 +46,4 @@ Source: src/WC.java - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/src/sample/share/try-with-resources/index.html --- a/jdk/src/sample/share/try-with-resources/index.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/src/sample/share/try-with-resources/index.html Tue Sep 08 15:39:51 2015 -0700 @@ -33,4 +33,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/ProblemList.txt Tue Sep 08 15:39:51 2015 -0700 @@ -319,6 +319,9 @@ # jdk_time +# 8134979 +java/time/tck/java/time/chrono/TCKJapaneseChronology.java generic-all + ############################################################################ # jdk_tools @@ -384,6 +387,11 @@ # 6456333 sun/tools/jps/TestJpsJarRelative.java generic-all +# 8134420 +sun/tools/jps/TestJpsClass.java generic-all +sun/tools/jps/TestJpsJar.java generic-all +sun/tools/jps/TestJpsSanity.java generic-all + # 6734748 sun/tools/jinfo/JInfoRunningProcessFlagTest.java generic-all diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/TEST.ROOT --- a/jdk/test/TEST.ROOT Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/TEST.ROOT Tue Sep 08 15:39:51 2015 -0700 @@ -18,7 +18,7 @@ othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation java/lang/ProcessHandle # Tests that cannot run concurrently -exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream javax/rmi sun/tools/jps +exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream javax/rmi # Group definitions groups=TEST.groups [closed/TEST.groups] diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/awt/SecurityWarning/GetSizeShouldNotReturnZero.java --- a/jdk/test/com/sun/awt/SecurityWarning/GetSizeShouldNotReturnZero.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/awt/SecurityWarning/GetSizeShouldNotReturnZero.java Tue Sep 08 15:39:51 2015 -0700 @@ -374,5 +374,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.NoSuchAlgorithmException; + +/* + * @test + * @bug 8048601 + * @library ../ + * @summary Test Blowfish cipher with different MODES and padding + */ + +public class TestCipherBlowfish extends TestCipher { + + TestCipherBlowfish() throws NoSuchAlgorithmException { + super("Blowfish", + new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC", + //CFBx + "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56", + "CFB64", + //OFBx + "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56", + "OFB64"}, + new String[]{"NoPaDDing", "PKCS5Padding"}, + true); + } + + public static void main(String[] args) throws Exception { + new TestCipherBlowfish().runAll(); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDES.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDES.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8048601 + * @library ../ + * @summary Test DES/DESede cipher with different MODES and padding + */ + +public class TestCipherDES extends TestCipher { + + TestCipherDES() { + super("DES", + new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC", + //CFBx + "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56", + "CFB64", + //OFBx + "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56", + "OFB64"}, + new String[]{"NoPaDDing", "PKCS5Padding"}); + } + + public static void main(String[] args) throws Exception { + new TestCipherDES().runAll(); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDESede.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDESede.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8048601 + * @library ../ + * @summary Test DES/DESede cipher with different MODES and padding + */ + +public class TestCipherDESede extends TestCipher { + + TestCipherDESede() { + super("DESede", + new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC", + //CFBx + "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56", + "CFB64", + //OFBx + "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56", + "OFB64"}, + new String[]{"NoPaDDing", "PKCS5Padding"}); + } + + public static void main(String[] args) throws Exception { + new TestCipherDESede().runAll(); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; + +/* + * @test + * @bug 8048601 + * @summary Tests for PBE ciphers + */ +public class TestCipherPBE { + + private static final String[] ALGORITHMS = {"PBEWithMD5AndDES", + "PBEWithMD5AndDES/CBC/PKCS5Padding", "PBEWithMD5AndTripleDES", + "PBEWithMD5AndTripleDES/CBC/PKCS5Padding"}; + + private static final String KEY_ALGO = "pbeWithMD5ANDdes"; + private final byte[] SALT; + private final byte[] PLAIN_TEXT; + + public TestCipherPBE() { + SALT = generateBytes(8); + PLAIN_TEXT = generateBytes(200); + } + + public static void main(String[] args) throws Exception { + + new TestCipherPBE().runAll(); + } + + private void runAll() throws Exception { + for (String algorithm : ALGORITHMS) { + runTest(algorithm); + } + } + + private void runTest(String algorithm) + throws InvalidKeySpecException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException, ShortBufferException, + NoSuchPaddingException, IllegalBlockSizeException, + BadPaddingException, InvalidKeyException { + + out.println("=> Testing: " + algorithm); + + try { + // Initialization + AlgorithmParameterSpec algoParamSpec + = new PBEParameterSpec(SALT, 6); + + SecretKey secretKey + = SecretKeyFactory.getInstance(KEY_ALGO).generateSecret( + new PBEKeySpec(("Secret Key Value").toCharArray())); + + Cipher ci = Cipher.getInstance(algorithm); + ci.init(Cipher.ENCRYPT_MODE, secretKey, algoParamSpec); + + // Encryption + byte[] cipherText = ci.doFinal(PLAIN_TEXT); + + // Decryption + ci.init(Cipher.DECRYPT_MODE, secretKey, algoParamSpec); + byte[] recoveredText = ci.doFinal(cipherText); + + if (algorithm.contains("TripleDES")) { + throw new RuntimeException( + "Expected InvalidKeyException exception uncaugh"); + } + + // Comparison + if (!Arrays.equals(PLAIN_TEXT, recoveredText)) { + throw new RuntimeException( + "Test failed: plainText is not equal to recoveredText"); + } + out.println("Test Passed."); + } catch (InvalidKeyException ex) { + if (algorithm.contains("TripleDES")) { + out.println("Expected InvalidKeyException raised"); + } else { + throw new RuntimeException(ex); + } + } + } + + public static byte[] generateBytes(int length) { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) { + bytes[i] = (byte) (i & 0xff); + } + return bytes; + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * This is a abstract class used to test various ciphers + */ +public abstract class TestCipher { + + private final String SUNJCE = "SunJCE"; + private final String ALGORITHM; + private final String[] MODES; + private final String[] PADDINGS; + + /* Used to test cipher with different key strengths + Key size tested is increment of KEYCUTTER from MINIMUM_KEY_SIZE to + maximum allowed keysize. + DES/DESede/Blowfish work with currently selected key sizes. + */ + private final int variousKeySize; + private final int KEYCUTTER = 8; + private final int MINIMUM_KEY_SIZE = 32; + + // Used to assert that Encryption/Decryption works with same buffer + // TEXT_LEN is multiple of blocks in order to work against ciphers w/ NoPadding + private final int TEXT_LEN = 800; + private final int ENC_OFFSET = 6; + private final int STORAGE_OFFSET = 3; + private final int PAD_BYTES = 16; + + private final byte[] IV; + private final byte[] INPUT_TEXT; + + TestCipher(String algo, String[] modes, String[] paddings, + boolean keyStrength) throws NoSuchAlgorithmException { + ALGORITHM = algo; + MODES = modes; + PADDINGS = paddings; + this.variousKeySize + = keyStrength ? Cipher.getMaxAllowedKeyLength(ALGORITHM) : 0; + + IV = generateBytes(8); + INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET); + } + + TestCipher(String algo, String[] modes, String[] paddings) { + ALGORITHM = algo; + MODES = modes; + PADDINGS = paddings; + variousKeySize = 0; + + IV = generateBytes(8); + INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET); + } + + private static byte[] generateBytes(int length) { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) { + bytes[i] = (byte) (i & 0xff); + } + return bytes; + } + + private boolean isKeyStrenthSupported() { + return (variousKeySize != 0); + } + + public void runAll() throws InvalidKeyException, + NoSuchPaddingException, InvalidAlgorithmParameterException, + ShortBufferException, IllegalBlockSizeException, + BadPaddingException, NoSuchAlgorithmException, + NoSuchProviderException { + + for (String mode : MODES) { + for (String padding : PADDINGS) { + if (!isKeyStrenthSupported()) { + runTest(mode, padding, 0); + } else { + int keySize = variousKeySize; + while (keySize >= MINIMUM_KEY_SIZE) { + out.println("With Key Strength: " + keySize); + runTest(mode, padding, keySize); + keySize -= KEYCUTTER; + } + } + } + } + } + + private void runTest(String mo, String pad, int keySize) + throws NoSuchPaddingException, BadPaddingException, + ShortBufferException, IllegalBlockSizeException, + InvalidAlgorithmParameterException, InvalidKeyException, + NoSuchAlgorithmException, NoSuchProviderException { + + String TRANSFORMATION = ALGORITHM + "/" + mo + "/" + pad; + out.println("Testing: " + TRANSFORMATION); + + // Initialization + Cipher ci = Cipher.getInstance(TRANSFORMATION, SUNJCE); + KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, SUNJCE); + if (keySize != 0) { + kg.init(keySize); + } + SecretKey key = kg.generateKey(); + SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), ALGORITHM); + + AlgorithmParameterSpec aps = new IvParameterSpec(IV); + if (mo.equalsIgnoreCase("ECB")) { + ci.init(Cipher.ENCRYPT_MODE, key); + } else { + ci.init(Cipher.ENCRYPT_MODE, key, aps); + } + + // Encryption + int PAD_LEN = 0; + if (pad.equalsIgnoreCase("PKCS5Padding")) { + // Need to consider pad bytes + PAD_LEN = 8; + } + + byte[] plainText = INPUT_TEXT.clone(); + + // Generate cipher and save to separate buffer + byte[] cipherText = ci.doFinal(INPUT_TEXT, ENC_OFFSET, TEXT_LEN); + + // Generate cipher and save to same buffer + int offset = ci.update( + INPUT_TEXT, ENC_OFFSET, TEXT_LEN, INPUT_TEXT, STORAGE_OFFSET); + ci.doFinal(INPUT_TEXT, offset + STORAGE_OFFSET); + + if (!equalsBlock( + INPUT_TEXT, STORAGE_OFFSET, cipherText, 0, cipherText.length)) { + throw new RuntimeException( + "Different ciphers generated with same buffer"); + } + + // Decryption + if (mo.equalsIgnoreCase("ECB")) { + ci.init(Cipher.DECRYPT_MODE, skeySpec); + } else { + ci.init(Cipher.DECRYPT_MODE, skeySpec, aps); + } + + // Recover text from cipher and save to separate buffer + byte[] recoveredText = ci.doFinal(cipherText, 0, cipherText.length); + + if (!equalsBlock( + plainText, ENC_OFFSET, recoveredText, 0, + recoveredText.length)) { + throw new RuntimeException( + "Recovered text not same as plain text"); + } else { + out.println("Recovered and plain text are same"); + } + + // Recover text from cipher and save to same buffer + ci.update(INPUT_TEXT, STORAGE_OFFSET, TEXT_LEN + PAD_LEN, INPUT_TEXT, + ENC_OFFSET); + ci.doFinal(INPUT_TEXT, ENC_OFFSET); + + if (!equalsBlock( + plainText, ENC_OFFSET, recoveredText, 0, + recoveredText.length)) { + throw new RuntimeException( + "Recovered text not same as plain text with same buffer"); + } else { + out.println("Recovered and plain text are same with same buffer"); + } + + out.println("Test Passed."); + } + + private static boolean equalsBlock(byte[] b1, int off1, byte[] b2, int off2, + int len) { + for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) { + if (b1[i] != b2[j]) { + return false; + } + } + return true; + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/TextLength/DESCipherWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/DESCipherWrapper.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; + +/** + * Wrapper class to test a given DES algorithm. + */ +public class DESCipherWrapper { + + private final Cipher ci; + private final byte[] iv; + private final SecretKey key; + private final String algo; + private final String mode; + private final String pad; + private final int keyStrength; + private byte[] resultText = null; + + public DESCipherWrapper(String algo, String mode, String pad) + throws NoSuchAlgorithmException, NoSuchPaddingException { + ci = Cipher.getInstance(algo + "/" + mode + "/" + pad); + + iv = new byte[8]; + for (int i = 0; i < 8; i++) { + iv[i] = (byte) (i & 0xff); + } + + KeyGenerator kg = KeyGenerator.getInstance(algo); + key = kg.generateKey(); + keyStrength = algo.equalsIgnoreCase("DESede") ? 112 + : key.getEncoded().length * 8; + + this.algo = algo; + this.mode = mode; + this.pad = pad; + } + + public byte[] getResult() { + return resultText.clone(); + } + + public void execute(int edMode, byte[] inputText) + throws InvalidKeyException, InvalidAlgorithmParameterException, + IllegalBlockSizeException, BadPaddingException, + ShortBufferException, NoSuchAlgorithmException { + AlgorithmParameterSpec aps = null; + + try { + if (!mode.equalsIgnoreCase("ECB")) { + aps = new IvParameterSpec(iv); + } + ci.init(edMode, key, aps); + + // Generate a resultText using a single-part enc/dec + resultText = ci.doFinal(inputText); + + // Generate outputText for each multi-part en/de-cryption + /* Combination #1: + update(byte[], int, int) + doFinal(byte[], int, int) + */ + byte[] part11 = ci.update(inputText, 0, inputText.length); + byte[] part12 = ci.doFinal(); + byte[] outputText1 = new byte[part11.length + part12.length]; + System.arraycopy(part11, 0, outputText1, 0, part11.length); + System.arraycopy(part12, 0, outputText1, part11.length, + part12.length); + + List outputTexts = new ArrayList<>(4); + outputTexts.add(outputText1); + + /* Combination #2: + update(byte[], int, int) + doFinal(byte[], int, int, byte[], int) + */ + byte[] part21 = ci.update(inputText, 0, inputText.length - 5); + byte[] part22 = new byte[ci.getOutputSize(inputText.length)]; + int len2 = ci + .doFinal(inputText, inputText.length - 5, 5, part22, 0); + byte[] outputText2 = new byte[part21.length + len2]; + System.arraycopy(part21, 0, outputText2, 0, part21.length); + System.arraycopy(part22, 0, outputText2, part21.length, len2); + + outputTexts.add(outputText2); + + /* Combination #3: + update(byte[], int, int, byte[], int) + doFinal(byte[], int, int) + */ + byte[] part31 = new byte[ci.getOutputSize(inputText.length)]; + int len3 = ci.update(inputText, 0, inputText.length - 8, part31, 0); + byte[] part32 = ci.doFinal(inputText, inputText.length - 8, 8); + byte[] outputText3 = new byte[len3 + part32.length]; + System.arraycopy(part31, 0, outputText3, 0, len3); + System.arraycopy(part32, 0, outputText3, len3, part32.length); + + outputTexts.add(outputText3); + + /* Combination #4: + update(byte[], int, int, byte[], int) + doFinal(byte[], int, int, byte[], int) + */ + byte[] part41 = new byte[ci.getOutputSize(inputText.length)]; + int len4 = ci.update(inputText, 0, inputText.length - 8, part41, 0); + int rest4 = ci.doFinal(inputText, inputText.length - 8, 8, part41, + len4); + byte[] outputText4 = new byte[len4 + rest4]; + System.arraycopy(part41, 0, outputText4, 0, outputText4.length); + + outputTexts.add(outputText4); + + // Compare results + for (int k = 0; k < outputTexts.size(); k++) { + if (!Arrays.equals(resultText, outputTexts.get(k))) { + out.println(" Testing: " + algo + "/" + mode + "/" + pad); + throw new RuntimeException( + "Compare value of resultText and combination " + k + + " are not same. Test failed."); + } + } + if (keyStrength > Cipher.getMaxAllowedKeyLength(algo)) { + throw new RuntimeException( + "Expected exception uncaught, keyStrength " + + keyStrength); + } + } catch (InvalidKeyException ex) { + if (keyStrength <= Cipher.getMaxAllowedKeyLength(algo)) { + out.println("Unexpected exception in " + algo + "/" + mode + + "/" + pad + " , KeySize " + keyStrength); + throw ex; + } + out.println("Caught InvalidKeyException as expected"); + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/TextLength/PBECipherWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/PBECipherWrapper.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * PBECipherWrapper is the abstract class for all concrete PBE Cipher wrappers. + */ +public abstract class PBECipherWrapper { + + public static final int ITERATION_COUNT = 1000; + private final String algorithm; + private final byte[] salt; + protected SecretKey key; + protected Cipher ci; + protected String baseAlgo; + protected byte[] resultText = null; + protected AlgorithmParameterSpec aps = null; + + public PBECipherWrapper(String algorithm, int saltSize) { + this.algorithm = algorithm; + baseAlgo = algorithm.split("/")[0].toUpperCase(); + salt = generateSalt(saltSize); + } + + protected abstract void initCipher(int mode) throws InvalidKeyException, + InvalidAlgorithmParameterException, InvalidParameterSpecException; + + public void execute(int edMode, byte[] inputText) + throws InvalidAlgorithmParameterException, + InvalidParameterSpecException, IllegalBlockSizeException, + BadPaddingException, ShortBufferException, InvalidKeyException { + // Initialize + initCipher(edMode); + + // Generate a resultText using a single-part enc/dec + resultText = ci.doFinal(inputText); + + // Generate outputText for each multi-part en/de-cryption + /* Combination #1: + update(byte[], int, int) + doFinal(byte[], int, int) + */ + byte[] part11 = ci.update(inputText, 0, inputText.length); + byte[] part12 = ci.doFinal(); + byte[] outputText1 = new byte[part11.length + part12.length]; + System.arraycopy(part11, 0, outputText1, 0, part11.length); + System.arraycopy(part12, 0, outputText1, part11.length, part12.length); + + List outputTexts = new ArrayList<>(4); + outputTexts.add(outputText1); + + /* Combination #2: + update(byte[], int, int) + doFinal(byte[], int, int, byte[], int) + */ + byte[] part21 = ci.update(inputText, 0, inputText.length - 5); + byte[] part22 = new byte[ci.getOutputSize(inputText.length)]; + int len2 = ci.doFinal(inputText, inputText.length - 5, 5, part22, 0); + byte[] outputText2 = new byte[part21.length + len2]; + System.arraycopy(part21, 0, outputText2, 0, part21.length); + System.arraycopy(part22, 0, outputText2, part21.length, len2); + + outputTexts.add(outputText2); + + /* Combination #3: + update(byte[], int, int, byte[], int) + doFinal(byte[], int, int) + */ + byte[] part31 = new byte[ci.getOutputSize(inputText.length)]; + int len3 = ci.update(inputText, 0, inputText.length - 8, part31, 0); + byte[] part32 = ci.doFinal(inputText, inputText.length - 8, 8); + byte[] outputText3 = new byte[len3 + part32.length]; + System.arraycopy(part31, 0, outputText3, 0, len3); + System.arraycopy(part32, 0, outputText3, len3, part32.length); + + outputTexts.add(outputText3); + + /* Combination #4: + update(byte[], int, int, byte[], int) + doFinal(byte[], int, int, byte[], int) + */ + byte[] part41 = new byte[ci.getOutputSize(inputText.length)]; + int len4 = ci.update(inputText, 0, inputText.length - 8, part41, 0); + int rest4 = ci + .doFinal(inputText, inputText.length - 8, 8, part41, len4); + byte[] outputText4 = new byte[len4 + rest4]; + System.arraycopy(part41, 0, outputText4, 0, outputText4.length); + + outputTexts.add(outputText4); + + // Compare results + for (int k = 0; k < outputTexts.size(); k++) { + if (!Arrays.equals(resultText, outputTexts.get(k))) { + throw new RuntimeException( + "Compare value of resultText and combination " + k + + " are not same. Test failed."); + } + } + + } + + public final byte[] generateSalt(int numberOfBytes) { + byte[] aSalt = new byte[numberOfBytes]; + for (int i = 0; i < numberOfBytes; i++) { + aSalt[i] = (byte) (i & 0xff); + } + return aSalt; + } + + public byte[] getResult() { + return resultText; + } + + public String getAlgorithm() { + return algorithm; + } + + public byte[] getSalt() { + return salt; + } + + /** + * Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm. + */ + public static class PBKDF2 extends PBECipherWrapper { + + private static final int PBKDF2_SALT_SIZE = 64; + private static final int CIPHER_KEY_SIZE = 128; + private static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding"; + private static final String KEY_ALGORITHM = "AES"; + private byte[] iv = null; + + public PBKDF2(String algo, String passwd) + throws InvalidKeySpecException, NoSuchAlgorithmException, + NoSuchPaddingException { + super(algo, PBKDF2_SALT_SIZE); + + ci = Cipher.getInstance(CIPHER_TRANSFORMATION); + + PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), getSalt(), + ITERATION_COUNT, CIPHER_KEY_SIZE); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algo); + key = keyFactory.generateSecret(pbeKeySpec); + } + + @Override + protected void initCipher(int mode) throws InvalidKeyException, + InvalidAlgorithmParameterException, InvalidParameterSpecException { + if (Cipher.ENCRYPT_MODE == mode) { + ci.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getEncoded(), + KEY_ALGORITHM)); + iv = ci.getParameters().getParameterSpec(IvParameterSpec.class) + .getIV(); + } else { + ci.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getEncoded(), + KEY_ALGORITHM), new IvParameterSpec(iv)); + } + } + } + + /** + * Wrapper class to test a given AES-based PBE algorithm. + */ + public static class AES extends PBECipherWrapper { + + private AlgorithmParameters pbeParams; + + public AES(String algo, String passwd) + throws NoSuchAlgorithmException, NoSuchPaddingException, + InvalidKeySpecException { + super(algo, 0); + + ci = Cipher.getInstance(algo); + + SecretKeyFactory skf = SecretKeyFactory.getInstance(algo); + key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray())); + } + + @Override + protected void initCipher(int mode) throws InvalidKeyException, + InvalidAlgorithmParameterException, InvalidParameterSpecException { + if (Cipher.ENCRYPT_MODE == mode) { + ci.init(Cipher.ENCRYPT_MODE, key); + pbeParams = ci.getParameters(); + } else { + ci.init(Cipher.DECRYPT_MODE, key, pbeParams); + } + } + } + + /** + * Wrapper class to test a given PBE algorithm. + */ + public static class Legacy extends PBECipherWrapper { + + private static final int PBE_SALT_SIZE = 8; + + public Legacy(String algo, String passwd) + throws NoSuchAlgorithmException, NoSuchPaddingException, + InvalidKeySpecException { + super(algo, PBE_SALT_SIZE); + + SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.split("/")[0]); + key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray())); + + aps = new PBEParameterSpec(getSalt(), ITERATION_COUNT); + + ci = Cipher.getInstance(algo); + } + + @Override + protected void initCipher(int mode) throws InvalidKeyException, + InvalidAlgorithmParameterException, InvalidParameterSpecException { + ci.init(mode, key, aps); + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Cipher/TextLength/TestCipherTextLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/TestCipherTextLength.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.System.out; + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +/* + * @test + * @bug 8048601 + * @summary Performs multiple-part encryption/decryption depending on the + * specified encryption mode and check if the results obtained by + * different ways are the same. + */ +public class TestCipherTextLength { + + /* Algorithms tested by DESCipherWrapper */ + private static final String[] DES_ALGORITHMS = {"DES", "DESede", + "Blowfish"}; + private static final String[] DES_MODES = {"ECB", "CBC", "PCBC"}; + private static final String[] DES_PADDING = {"PKCS5Padding"}; + + /* Algorithms tested by PBECipherWrapper */ + private static final String[] PBE_ALGORITHMS = {"PBEWithMD5AndDES", + "PBEWithMD5AndDES/CBC/PKCS5Padding", "PBEWithMD5ANDTripleDES", + "PBEWithMD5AndTripleDES/CBC/PKCS5Padding", "PBEwithSHA1AndDESede", + "PBEwithSHA1AndDESede/CBC/PKCS5Padding", "PBEwithSHA1AndRC2_40", + "PBEwithSHA1Andrc2_40/CBC/PKCS5Padding", "PBEWithSHA1AndRC2_128", + "PBEWithSHA1andRC2_128/CBC/PKCS5Padding", "PBEWithSHA1AndRC4_40", + "PBEWithsha1AndRC4_40/ECB/NoPadding", "PBEWithSHA1AndRC4_128", + "PBEWithSHA1AndRC4_128/ECB/NoPadding", "PBEWithHmacSHA1AndAES_128", + "PBEWithHmacSHA224AndAES_128", "PBEWithHmacSHA256AndAES_128", + "PBEWithHmacSHA384AndAES_128", "PBEWithHmacSHA512AndAES_128", + "PBEWithHmacSHA1AndAES_256", "PBEWithHmacSHA224AndAES_256", + "PBEWithHmacSHA256AndAES_256", "PBEWithHmacSHA384AndAES_256", + "PBEWithHmacSHA512AndAES_256", "PBKDF2WithHmacSHA1", + "PBKDF2WithHmacSHA224", "PBKDF2WithHmacSHA256", + "PBKDF2WithHmacSHA384", "PBKDF2WithHmacSHA512"}; + private static final String PBE_PASSWORD = "Hush, it's a secret!!"; + + // Algorithm tested by PBKDF2Wrappter + private static final String PBKDF2 = "PBKDF2"; + + // Algorithm tested by AESPBEWrapper + private static final String AES = "AES"; + + public static void main(String[] args) throws Exception { + byte[] plainText = new byte[64]; + for (int i = 0; i < 64; i++) { + plainText[i] = (byte) (i & 0xff); + } + + new TestCipherTextLength().runAll(plainText); + } + + public void runAll(byte[] plainText) throws Exception { + + // Testing DES/Blowfish Cipher + for (String algorithm : DES_ALGORITHMS) { + for (String desMode : DES_MODES) { + for (String padding : DES_PADDING) { + out.println("=>Testing: " + algorithm + "/" + desMode + + "/" + padding); + DESCipherWrapper desCi = new DESCipherWrapper(algorithm, + desMode, padding); + desCi.execute(Cipher.ENCRYPT_MODE, plainText); + desCi.execute(Cipher.DECRYPT_MODE, desCi.getResult()); + if (!Arrays.equals(plainText, desCi.getResult())) { + throw new RuntimeException( + "Plain and recovered texts are not same for:" + + algorithm + "/" + desMode + "/" + + padding); + } + } + } + } + + // Testing PBE Cipher + for (String algorithm : PBE_ALGORITHMS) { + int maxKeyLen = Cipher.getMaxAllowedKeyLength(algorithm); + boolean isUnlimited = maxKeyLen == Integer.MAX_VALUE; + if (!isUnlimited + && (algorithm.contains("TripleDES") || algorithm + .contains("AES_256"))) { + out.println("Test " + algorithm + " will be ignored"); + continue; + } + + out.println("=>Testing: " + algorithm); + PBECipherWrapper pbeCi = createWrapper(algorithm, PBE_PASSWORD); + pbeCi.execute(Cipher.ENCRYPT_MODE, plainText); + pbeCi.execute(Cipher.DECRYPT_MODE, pbeCi.getResult()); + if (!Arrays.equals(plainText, pbeCi.getResult())) { + throw new RuntimeException( + "Plain and recovered texts are not same for:" + + algorithm); + } + } + } + + private PBECipherWrapper createWrapper(String algo, String passwd) + throws InvalidKeySpecException, NoSuchAlgorithmException, + NoSuchPaddingException { + if (algo.contains(PBKDF2)) { + return new PBECipherWrapper.PBKDF2(algo, passwd); + } else if (algo.contains(AES)) { + return new PBECipherWrapper.AES(algo, passwd); + } else { + return new PBECipherWrapper.Legacy(algo, passwd); + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/crypto/provider/Mac/Utils.java --- a/jdk/test/com/sun/crypto/provider/Mac/Utils.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/crypto/provider/Mac/Utils.java Tue Sep 08 15:39:51 2015 -0700 @@ -76,4 +76,4 @@ interface MacTest { void doTest(String alg) throws Exception; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jdi/InterfaceMethodsTest.java --- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -442,6 +442,3 @@ } } } - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jdi/ShellScaffold.sh --- a/jdk/test/com/sun/jdi/ShellScaffold.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh Tue Sep 08 15:39:51 2015 -0700 @@ -1215,5 +1215,3 @@ # Don't know how this arises debuggeeFailIfPresent "Internal exception" } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/ConfigKey.java --- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/ConfigKey.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/ConfigKey.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,4 +23,4 @@ public enum ConfigKey { CONSTANT3, CONSTANT2; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/ConfigKey.java --- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/ConfigKey.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/ConfigKey.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,4 +23,4 @@ public enum ConfigKey { CONSTANT1, CONSTANT2; -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Ste.java --- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Ste.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Ste.java Tue Sep 08 15:39:51 2015 -0700 @@ -29,4 +29,4 @@ public void foo() { sendNotification(new TestNotification("test", this, count++)); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/SteMBean.java --- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/SteMBean.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/SteMBean.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,4 +23,4 @@ public interface SteMBean { public void foo(); -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy --- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Tue Sep 08 15:39:51 2015 -0700 @@ -7,5 +7,3 @@ //permission java.net.SocketPermission "*:636", "connect"; //permission javax.security.auth.AuthPermission "modifyPrincipals"; }; - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java --- a/jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java Tue Sep 08 15:39:51 2015 -0700 @@ -212,4 +212,4 @@ throw new RuntimeException(e); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java --- a/jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java Tue Sep 08 15:39:51 2015 -0700 @@ -163,4 +163,4 @@ throw new RuntimeException(e); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java --- a/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java Tue Sep 08 15:39:51 2015 -0700 @@ -69,4 +69,4 @@ } }); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.html --- a/jdk/test/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.html Tue Sep 08 15:39:51 2015 -0700 @@ -29,4 +29,4 @@

See the dialog box (usually in upper left corner) for instructions

- \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java --- a/jdk/test/java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -134,4 +134,4 @@ throw new RuntimeException("file chooser is underneath"); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Focus/6981400/Test3.java --- a/jdk/test/java/awt/Focus/6981400/Test3.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Focus/6981400/Test3.java Tue Sep 08 15:39:51 2015 -0700 @@ -135,5 +135,3 @@ } } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/FontClass/LCDScale.java --- a/jdk/test/java/awt/FontClass/LCDScale.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/FontClass/LCDScale.java Tue Sep 08 15:39:51 2015 -0700 @@ -79,5 +79,3 @@ } } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Frame/FramesGC/FramesGC.java --- a/jdk/test/java/awt/Frame/FramesGC/FramesGC.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Frame/FramesGC/FramesGC.java Tue Sep 08 15:39:51 2015 -0700 @@ -156,4 +156,4 @@ refs.add(new PhantomReference(frame, que)); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java --- a/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java Tue Sep 08 15:39:51 2015 -0700 @@ -76,4 +76,4 @@ frame.dispose(); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java --- a/jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java Tue Sep 08 15:39:51 2015 -0700 @@ -129,4 +129,4 @@ checkMenuCount(menuBar, 0); checkHelpMenu(helpMenu, false); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mixing/JButtonInGlassPane.java --- a/jdk/test/java/awt/Mixing/JButtonInGlassPane.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mixing/JButtonInGlassPane.java Tue Sep 08 15:39:51 2015 -0700 @@ -426,5 +426,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mixing/LWComboBox.java --- a/jdk/test/java/awt/Mixing/LWComboBox.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mixing/LWComboBox.java Tue Sep 08 15:39:51 2015 -0700 @@ -421,5 +421,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mixing/MixingInHwPanel.java --- a/jdk/test/java/awt/Mixing/MixingInHwPanel.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mixing/MixingInHwPanel.java Tue Sep 08 15:39:51 2015 -0700 @@ -424,5 +424,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java --- a/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java Tue Sep 08 15:39:51 2015 -0700 @@ -425,5 +425,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java --- a/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java Tue Sep 08 15:39:51 2015 -0700 @@ -430,5 +430,3 @@ } }// TestDialog class - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java --- a/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -100,4 +100,4 @@ frame.add(panel, BorderLayout.CENTER); frame.setVisible(true); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/MouseInfo/JContainerMousePositionTest.java --- a/jdk/test/java/awt/MouseInfo/JContainerMousePositionTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/MouseInfo/JContainerMousePositionTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -144,5 +144,3 @@ frame1.setVisible(true); } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java --- a/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -80,4 +80,4 @@ } } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/ScrollPane/bug8077409Test.java --- a/jdk/test/java/awt/ScrollPane/bug8077409Test.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/ScrollPane/bug8077409Test.java Tue Sep 08 15:39:51 2015 -0700 @@ -112,4 +112,4 @@ } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java --- a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -148,4 +148,4 @@ "JPopupMenu shown and menu item selected using keyboard"); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java --- a/jdk/test/java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -59,4 +59,4 @@ window.setVisible(true); return window; } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/applet/Applet/AppletFlipBuffer.java --- a/jdk/test/java/awt/applet/Applet/AppletFlipBuffer.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/applet/Applet/AppletFlipBuffer.java Tue Sep 08 15:39:51 2015 -0700 @@ -52,4 +52,4 @@ frame.dispose(); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/test.html --- a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/test.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/test.html Tue Sep 08 15:39:51 2015 -0700 @@ -41,4 +41,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java --- a/jdk/test/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -168,4 +168,4 @@ } } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java --- a/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -342,4 +342,4 @@ } } -}// TestDialog class \ No newline at end of file +}// TestDialog class diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/datatransfer/MissedHtmlAndRtfBug/MyTransferable.java --- a/jdk/test/java/awt/datatransfer/MissedHtmlAndRtfBug/MyTransferable.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/datatransfer/MissedHtmlAndRtfBug/MyTransferable.java Tue Sep 08 15:39:51 2015 -0700 @@ -59,4 +59,4 @@ throw new UnsupportedFlavorException(flavor); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java --- a/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java Tue Sep 08 15:39:51 2015 -0700 @@ -120,5 +120,3 @@ frame.dispatchEvent( ( AWTEvent )meOld ); } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/im/4490692/bug4490692.html --- a/jdk/test/java/awt/im/4490692/bug4490692.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/im/4490692/bug4490692.html Tue Sep 08 15:39:51 2015 -0700 @@ -59,5 +59,3 @@ - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/awt/im/4959409/bug4959409.html --- a/jdk/test/java/awt/im/4959409/bug4959409.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/awt/im/4959409/bug4959409.html Tue Sep 08 15:39:51 2015 -0700 @@ -45,5 +45,3 @@ - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/beans/README --- a/jdk/test/java/beans/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/beans/README Tue Sep 08 15:39:51 2015 -0700 @@ -73,4 +73,4 @@ If this object is not null it will be encoded and decoded. Also the object updating will be tested in this case. The test() method has a boolean parameter, -which indicates that the test should be started in secure context. \ No newline at end of file +which indicates that the test should be started in secure context. diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/beans/SimpleBeanInfo/LoadingStandardIcons/java.policy --- a/jdk/test/java/beans/SimpleBeanInfo/LoadingStandardIcons/java.policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/beans/SimpleBeanInfo/LoadingStandardIcons/java.policy Tue Sep 08 15:39:51 2015 -0700 @@ -1,1 +1,1 @@ -; \ No newline at end of file +; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/io/Serializable/evolution/AddedSuperClass/README --- a/jdk/test/java/io/Serializable/evolution/AddedSuperClass/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/io/Serializable/evolution/AddedSuperClass/README Tue Sep 08 15:39:51 2015 -0700 @@ -12,6 +12,3 @@ rm A.class AddedSuperClass.class javac ReadAddedSuperClass2.java java ReadAddedSuperClass2 - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/lang/ClassLoader/getdotresource.sh --- a/jdk/test/java/lang/ClassLoader/getdotresource.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/lang/ClassLoader/getdotresource.sh Tue Sep 08 15:39:51 2015 -0700 @@ -44,5 +44,3 @@ # now start the test ${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTSRC}${FS}resource.jar${PS}${TESTCLASSES} GetDotResource - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.sh --- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.sh Tue Sep 08 15:39:51 2015 -0700 @@ -69,5 +69,3 @@ then echo "$failures test(s) failed"; else echo "All test(s) passed"; fi exit $failures - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/net/SocketPermission/policy --- a/jdk/test/java/net/SocketPermission/policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/net/SocketPermission/policy Tue Sep 08 15:39:51 2015 -0700 @@ -1,3 +1,3 @@ grant { permission java.security.AllPermission; -}; \ No newline at end of file +}; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/nio/channels/SocketChannel/Open.sh --- a/jdk/test/java/nio/channels/SocketChannel/Open.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/nio/channels/SocketChannel/Open.sh Tue Sep 08 15:39:51 2015 -0700 @@ -33,6 +33,3 @@ * ) echo "unrecognized system: $OS" ;; esac - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/README --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/README Tue Sep 08 15:39:51 2015 -0700 @@ -31,5 +31,3 @@ (c) Execute the make script :- Solaris: gnumake all Linux: gmake all - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java --- a/jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java Tue Sep 08 15:39:51 2015 -0700 @@ -21,17 +21,18 @@ * questions. */ -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; - /* @test * @summary Test probing content type simultaneously from multiple threads. * @requires (os.family == "linux") | (os.family == "solaris") * @build ParallelProbes SimpleFileTypeDetector * @run main/othervm ParallelProbes 10 */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; + public class ParallelProbes { private static final int REPEATS = 1000; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/rmi/registry/readTest/readTest.sh --- a/jdk/test/java/rmi/registry/readTest/readTest.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/rmi/registry/readTest/readTest.sh Tue Sep 08 15:39:51 2015 -0700 @@ -125,5 +125,3 @@ fi rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp exit ${exitCode} - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/security/KeyStore/PKCS12/README --- a/jdk/test/java/security/KeyStore/PKCS12/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/security/KeyStore/PKCS12/README Tue Sep 08 15:39:51 2015 -0700 @@ -25,4 +25,4 @@ 3. Import certificate /bin/keytool -import -alias pkcs12test -keystore ks-pkcs.data --storepass storepass -file pkcs12testCA.cer.data \ No newline at end of file +-storepass storepass -file pkcs12testCA.cer.data diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/security/SignedObject/Copy.java --- a/jdk/test/java/security/SignedObject/Copy.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/security/SignedObject/Copy.java Tue Sep 08 15:39:51 2015 -0700 @@ -119,5 +119,3 @@ } } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/AbstractCollection/ToArrayTest.java --- a/jdk/test/java/util/AbstractCollection/ToArrayTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/AbstractCollection/ToArrayTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -211,5 +211,3 @@ else {System.out.println(x + " not equal to " + y); fail(); } } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/Arrays/SetAllTest.java --- a/jdk/test/java/util/Arrays/SetAllTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/Arrays/SetAllTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -278,4 +278,4 @@ // expected } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/Locale/bug4123285.html --- a/jdk/test/java/util/Locale/bug4123285.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/Locale/bug4123285.html Tue Sep 08 15:39:51 2015 -0700 @@ -1,1 +1,1 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java --- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -120,4 +120,4 @@ Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException, "Incorrect exception passed to whenComplete: " + eOnWhenComplete.get()); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/logging/LogManager/Configuration/TestConfigurationLock.properties --- a/jdk/test/java/util/logging/LogManager/Configuration/TestConfigurationLock.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/logging/LogManager/Configuration/TestConfigurationLock.properties Tue Sep 08 15:39:51 2015 -0700 @@ -18,5 +18,3 @@ foo.bar.l10.level = INFO foo.bar.l100.level = INFO foo.bar.l1000.level = INFO - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/java/util/stream/bootlib/java/util/stream/DefaultMethodStreams.java --- a/jdk/test/java/util/stream/bootlib/java/util/stream/DefaultMethodStreams.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/DefaultMethodStreams.java Tue Sep 08 15:39:51 2015 -0700 @@ -981,4 +981,4 @@ s.close(); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/crypto/SecretKeyFactory/PBKDF2TranslateTest.java --- a/jdk/test/javax/crypto/SecretKeyFactory/PBKDF2TranslateTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/crypto/SecretKeyFactory/PBKDF2TranslateTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -267,4 +267,4 @@ } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/imageio/plugins/shared/CanWriteSequence.java --- a/jdk/test/javax/imageio/plugins/shared/CanWriteSequence.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/imageio/plugins/shared/CanWriteSequence.java Tue Sep 08 15:39:51 2015 -0700 @@ -75,4 +75,4 @@ writer.dispose(); ios.close(); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/management/MustBeValidMBeanInfo/logging.properties --- a/jdk/test/javax/management/MustBeValidMBeanInfo/logging.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/management/MustBeValidMBeanInfo/logging.properties Tue Sep 08 15:39:51 2015 -0700 @@ -11,4 +11,4 @@ java.util.logging.ConsoleHandler.level = FINEST java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -javax.management.misc.level = FINEST \ No newline at end of file +javax.management.misc.level = FINEST diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/management/ObjectName/CompressedStorageTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/ObjectName/CompressedStorageTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8041565 + * @summary Tests the limits imposed on the domain name part of an + * ObjectName instance + * @author Jaroslav Bachorik + * @modules java.management + * @run main CompressedStorageTest + */ + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.function.Consumer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +public class CompressedStorageTest { + private static Method setDomainLengthM; + private static Field compressedStorageFld; + + private static int DOMAIN_PATTERN; + private static int PROPLIST_PATTERN; + private static int PROPVAL_PATTERN; + + private static Method setDomainPattern; + private static Method setPropertyListPattern; + private static Method setPropertyValuePattern; + + + static { + try { + Class clz = ObjectName.class; + setDomainLengthM = clz.getDeclaredMethod("setDomainLength", int.class); + setDomainLengthM.setAccessible(true); + + compressedStorageFld = clz.getDeclaredField("_compressed_storage"); + compressedStorageFld.setAccessible(true); + + setDomainPattern = clz.getDeclaredMethod("setDomainPattern", boolean.class); + setDomainPattern.setAccessible(true); + setPropertyListPattern = clz.getDeclaredMethod("setPropertyListPattern", boolean.class); + setPropertyListPattern.setAccessible(true); + setPropertyValuePattern = clz.getDeclaredMethod("setPropertyValuePattern", boolean.class); + setPropertyValuePattern.setAccessible(true); + + DOMAIN_PATTERN = getStaticIntFld("DOMAIN_PATTERN"); + PROPLIST_PATTERN = getStaticIntFld("PROPLIST_PATTERN"); + PROPVAL_PATTERN = getStaticIntFld("PROPVAL_PATTERN"); + + } catch (Exception e) { + throw new Error(e); + } + } + + public static void main(String[] args) throws Exception { + testZeroLength(); + testNegativeLength(); + testMaxLength(); + + testSetDomainPattern(); + testSetPropertyListPattern(); + testSetPropertyValuePattern(); + } + + private static ObjectName getObjectName() + throws MalformedObjectNameException { + return new ObjectName("domain", "key", "value"); + } + + /** + * Test for accepting 0 being passed as argument to + * {@linkplain ObjectName#setDomainLength(int)}. + * + */ + private static void testZeroLength() throws Exception { + setDomainNameLength(0); + } + + /** + * Test for rejecting negative value being passed as argument to + * {@linkplain ObjectName#setDomainLength(int)}. + */ + private static void testNegativeLength() throws Exception { + try { + setDomainNameLength(-1); + } catch (MalformedObjectNameException e) { + return; + } + fail("Allowing negative domain name length"); + } + + /** + * Test for rejecting value exceeding the maximum allowed length + * being passed as argument to {@linkplain ObjectName#setDomainLength(int)}. + */ + private static void testMaxLength() throws Exception { + try { + setDomainNameLength(Integer.MAX_VALUE / 4 + 1); + } catch (MalformedObjectNameException e) { + return; + } + fail("Maximum domain name length is not respected"); + } + + /** + * Tests that calling {@linkplain ObjectName#setDomainPattern(boolean)} + * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}. + */ + private static void testSetDomainPattern() throws Exception { + ObjectName on = getObjectName(); + + checkMask(DOMAIN_PATTERN, setDomainPattern, on); + } + + /** + * Tests that calling {@linkplain ObjectName#setPropertyListPattern(boolean)} + * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}. + */ + private static void testSetPropertyListPattern() throws Exception { + ObjectName on = getObjectName(); + + checkMask(PROPLIST_PATTERN, setPropertyListPattern, on); + } + + /** + * Tests that calling {@linkplain ObjectName#setPropertyValuePattern(boolean)} + * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}. + */ + private static void testSetPropertyValuePattern() throws Exception { + ObjectName on = getObjectName(); + + checkMask(PROPVAL_PATTERN, setPropertyValuePattern, on); + } + + /** + * Helper method to call {@linkplain ObjectName#setDomainLength(int)} + * method via reflection. + * @param len The domain name length + * @throws MalformedObjectNameException Propagated from + * {@linkplain ObjectName#setDomainLength(int)} invocation. + */ + private static void setDomainNameLength(int len) + throws MalformedObjectNameException { + try { + setDomainLengthM.invoke(getObjectName(), len); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof MalformedObjectNameException) { + throw (MalformedObjectNameException)cause; + } + throw new Error(cause); + } catch (IllegalAccessException | IllegalArgumentException e) { + throw new Error(e); + } + } + + /** + * Helper method to assert that a particular boolean setter affects only + * a particular bit in the {@linkplain ObjectName#_compressed_storage} field. + * @param mask bitmask for storing the boolean value + * @param setter setter method reference + * @param on {@linkplain ObjectName} instance + */ + private static void checkMask(int mask, Method setter, ObjectName on) + throws Exception { + int valBefore = compressedStorageFld.getInt(on); + setter.invoke(on, true); + int valAfter = compressedStorageFld.getInt(on); + + checkMask(mask, valAfter ^ valBefore); + + valBefore = valAfter; + setter.invoke(on, false); + valAfter = compressedStorageFld.getInt(on); + + checkMask(mask, valAfter ^ valBefore); + } + + /** + * Compare the changed bits with the given mask. + * @param mask bitmask + * @param val the changed bits; may be 0 if there was no change + */ + private static void checkMask(int mask, int val) { + if (val != 0 && val != mask) { + fail("Invalid mask: expecting '" + + Integer.toBinaryString(mask) + "' , received '" + + Integer.toBinaryString(val) + "'"); + } + } + + /** + * Helper method to obtain the value of a static field via reflection. + * @param name static field name + * @return static field value + */ + private static int getStaticIntFld(String name) throws Exception { + Field fld = ObjectName.class.getDeclaredField(name); + fld.setAccessible(true); + + return fld.getInt(null); + } + + private static void fail(String msg) { + throw new Error(msg); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/management/modelmbean/SimpleModelMBean/logging.properties --- a/jdk/test/javax/management/modelmbean/SimpleModelMBean/logging.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/management/modelmbean/SimpleModelMBean/logging.properties Tue Sep 08 15:39:51 2015 -0700 @@ -11,4 +11,4 @@ java.util.logging.ConsoleHandler.level = FINEST java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -javax.management.misc.level = FINEST \ No newline at end of file +javax.management.misc.level = FINEST diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace --- a/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Tue Sep 08 15:39:51 2015 -0700 @@ -24,4 +24,4 @@ grant codeBase "file:ReadPropertyNegativeAction.jar" Principal javax.security.auth.x500.X500Principal "cn=Duke" { permission java.security.AllPermission; -}; \ No newline at end of file +}; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/security/auth/Subject/doAs/policy.one.principal --- a/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Tue Sep 08 15:39:51 2015 -0700 @@ -33,4 +33,4 @@ permission javax.security.auth.AuthPermission "getSubject"; permission javax.security.auth.AuthPermission "doAs"; permission java.util.PropertyPermission "java.class.path", "read"; -}; \ No newline at end of file +}; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/security/auth/Subject/doAs/policy.two.principals --- a/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Tue Sep 08 15:39:51 2015 -0700 @@ -34,4 +34,4 @@ permission javax.security.auth.AuthPermission "getSubject"; permission javax.security.auth.AuthPermission "doAs"; permission java.util.PropertyPermission "java.class.path", "read"; -}; \ No newline at end of file +}; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/security/auth/login/LoginContext/shared.config --- a/jdk/test/javax/security/auth/login/LoginContext/shared.config Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/security/auth/login/LoginContext/shared.config Tue Sep 08 15:39:51 2015 -0700 @@ -1,4 +1,4 @@ SharedState { SharedState$FirstModule required; SharedState$SecondModule required; -}; \ No newline at end of file +}; diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java --- a/jdk/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -184,5 +184,3 @@ } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JColorChooser/8065098/bug8065098.html --- a/jdk/test/javax/swing/JColorChooser/8065098/bug8065098.html Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JColorChooser/8065098/bug8065098.html Tue Sep 08 15:39:51 2015 -0700 @@ -37,4 +37,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JFileChooser/8062561/security2.policy --- a/jdk/test/javax/swing/JFileChooser/8062561/security2.policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JFileChooser/8062561/security2.policy Tue Sep 08 15:39:51 2015 -0700 @@ -1,1 +1,1 @@ -// Autogenerated file \ No newline at end of file +// Autogenerated file diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java --- a/jdk/test/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java Tue Sep 08 15:39:51 2015 -0700 @@ -82,4 +82,4 @@ return "CustomFileFilter"; } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java --- a/jdk/test/javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java Tue Sep 08 15:39:51 2015 -0700 @@ -195,4 +195,4 @@ } System.out.println("Test passed"); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java --- a/jdk/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java Tue Sep 08 15:39:51 2015 -0700 @@ -132,4 +132,4 @@ throw new RuntimeException(e); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JOptionPane/8081019/bug8081019.java --- a/jdk/test/javax/swing/JOptionPane/8081019/bug8081019.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JOptionPane/8081019/bug8081019.java Tue Sep 08 15:39:51 2015 -0700 @@ -103,4 +103,4 @@ throw new RuntimeException("Exception in the output!"); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt --- a/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt Tue Sep 08 15:39:51 2015 -0700 @@ -219,5 +219,3 @@ Copyright 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved. - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JTree/8072676/TreeClipTest.java --- a/jdk/test/javax/swing/JTree/8072676/TreeClipTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JTree/8072676/TreeClipTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -94,4 +94,4 @@ System.out.println("Passed."); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java --- a/jdk/test/javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java Tue Sep 08 15:39:51 2015 -0700 @@ -381,4 +381,4 @@ return nodesFlavor.equals(flavor); } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/UIDefaults/7180976/Pending.java --- a/jdk/test/javax/swing/UIDefaults/7180976/Pending.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/UIDefaults/7180976/Pending.java Tue Sep 08 15:39:51 2015 -0700 @@ -47,4 +47,4 @@ UIManager.get("foobar"); passed = true; } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java --- a/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java Tue Sep 08 15:39:51 2015 -0700 @@ -169,4 +169,4 @@ frame.setVisible(true); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/text/View/8015853/bug8015853.txt --- a/jdk/test/javax/swing/text/View/8015853/bug8015853.txt Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/text/View/8015853/bug8015853.txt Tue Sep 08 15:39:51 2015 -0700 @@ -64,4 +64,4 @@ frame.add(editorPane); frame.setVisible(true); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/text/html/8005391/bug8005391.java --- a/jdk/test/javax/swing/text/html/8005391/bug8005391.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/text/html/8005391/bug8005391.java Tue Sep 08 15:39:51 2015 -0700 @@ -58,4 +58,4 @@ } } } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/swing/text/html/HTMLDocument/8058120/bug8058120.java --- a/jdk/test/javax/swing/text/html/HTMLDocument/8058120/bug8058120.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/swing/text/html/HTMLDocument/8058120/bug8058120.java Tue Sep 08 15:39:51 2015 -0700 @@ -109,5 +109,3 @@ frame.setVisible(true); } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/bind/xjc/8032884/optional-property-schema.xsd --- a/jdk/test/javax/xml/bind/xjc/8032884/optional-property-schema.xsd Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/bind/xjc/8032884/optional-property-schema.xsd Tue Sep 08 15:39:51 2015 -0700 @@ -11,4 +11,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/parsers/8032909/a_utf16.xml diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/parsers/8032909/a_utf16.xsl diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml Tue Sep 08 15:39:51 2015 -0700 @@ -4,4 +4,4 @@ 2 2 3 - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd Tue Sep 08 15:39:51 2015 -0700 @@ -38,4 +38,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml Tue Sep 08 15:39:51 2015 -0700 @@ -1,2 +1,2 @@ --12345 \ No newline at end of file +-12345 diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml Tue Sep 08 15:39:51 2015 -0700 @@ -2,4 +2,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml Tue Sep 08 15:39:51 2015 -0700 @@ -2,4 +2,4 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd --- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd Tue Sep 08 15:39:51 2015 -0700 @@ -1,2 +1,2 @@ - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/javax/xml/jaxp/transform/8004476/tokenize.xml --- a/jdk/test/javax/xml/jaxp/transform/8004476/tokenize.xml Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/javax/xml/jaxp/transform/8004476/tokenize.xml Tue Sep 08 15:39:51 2015 -0700 @@ -4,4 +4,4 @@ Is this EXSLT? No. no Is this EXSLT? No. no - \ No newline at end of file + diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/jvmstat/testlibrary/utils.sh --- a/jdk/test/sun/jvmstat/testlibrary/utils.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/jvmstat/testlibrary/utils.sh Tue Sep 08 15:39:51 2015 -0700 @@ -221,5 +221,3 @@ fi echo "${port1}" } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java --- a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -57,5 +57,3 @@ } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java --- a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -61,5 +61,3 @@ test.runTest(args); } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java --- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -186,4 +186,4 @@ private Properties getCounters() throws IOException, InterruptedException { return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*"); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/management/jmxremote/startstop/REMOTE_TESTING.txt --- a/jdk/test/sun/management/jmxremote/startstop/REMOTE_TESTING.txt Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/management/jmxremote/startstop/REMOTE_TESTING.txt Tue Sep 08 15:39:51 2015 -0700 @@ -15,5 +15,3 @@ 6. connect jconsole to host2:50234 Make sure jconsole works Make sure only host2.50234 and host2.50235 appears in tcpdump output. - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/management/windows/README --- a/jdk/test/sun/management/windows/README Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/management/windows/README Tue Sep 08 15:39:51 2015 -0700 @@ -26,5 +26,3 @@ Note that a 32-bit version of revokeall.exe is checked into SCCS - this 32-bit application is also used when running on 64-bit versions of Windows (AMD64 and IA64). - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/net/www/http/HttpClient/IsKeepingAlive.policy --- a/jdk/test/sun/net/www/http/HttpClient/IsKeepingAlive.policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/net/www/http/HttpClient/IsKeepingAlive.policy Tue Sep 08 15:39:51 2015 -0700 @@ -45,5 +45,3 @@ permission java.util.PropertyPermission "java.vm.vendor", "read"; permission java.util.PropertyPermission "java.vm.name", "read"; }; - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/net/www/http/HttpClient/OpenServer.policy --- a/jdk/test/sun/net/www/http/HttpClient/OpenServer.policy Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/net/www/http/HttpClient/OpenServer.policy Tue Sep 08 15:39:51 2015 -0700 @@ -45,5 +45,3 @@ permission java.util.PropertyPermission "java.vm.vendor", "read"; permission java.util.PropertyPermission "java.vm.name", "read"; }; - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/net/www/protocol/http/spnegoTest --- a/jdk/test/sun/net/www/protocol/http/spnegoTest Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/net/www/protocol/http/spnegoTest Tue Sep 08 15:39:51 2015 -0700 @@ -205,4 +205,4 @@ rm err.log rm out.log -exit 0 \ No newline at end of file +exit 0 diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/ec/SignatureOffsets.java --- a/jdk/test/sun/security/ec/SignatureOffsets.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/ec/SignatureOffsets.java Tue Sep 08 15:39:51 2015 -0700 @@ -49,4 +49,4 @@ InvalidKeyException, SignatureException { Offsets.main(args); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/krb5/IPv6.java --- a/jdk/test/sun/security/krb5/IPv6.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/krb5/IPv6.java Tue Sep 08 15:39:51 2015 -0700 @@ -127,5 +127,3 @@ } } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh --- a/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Tue Sep 08 15:39:51 2015 -0700 @@ -132,6 +132,3 @@ exit 0 ;; esac - - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/mscapi/SignatureOffsets.java --- a/jdk/test/sun/security/mscapi/SignatureOffsets.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java Tue Sep 08 15:39:51 2015 -0700 @@ -50,4 +50,4 @@ InvalidKeyException, SignatureException { Offsets.main(args); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/pkcs11/Provider/Absolute.java --- a/jdk/test/sun/security/pkcs11/Provider/Absolute.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/pkcs11/Provider/Absolute.java Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,40 +22,31 @@ */ /** * @test - * @bug 7003952 + * @bug 7003952 7191662 + * @library .. * @summary load DLLs and launch executables using fully qualified path */ import java.security.*; -import java.lang.reflect.*; public class Absolute { public static void main(String[] args) throws Exception { - Constructor cons; - try { - Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11"); - cons = clazz.getConstructor(new Class[] {String.class}); - } catch (Exception ex) { - System.out.println("Skipping test - no PKCS11 provider available"); - return; - } - String config = System.getProperty("test.src", ".") + "/Absolute.cfg"; try { - Object obj = cons.newInstance(new Object[] {config}); - } catch (InvocationTargetException ite) { - Throwable cause = ite.getCause(); - if (cause instanceof ProviderException) { - Throwable cause2 = cause.getCause(); - if ((cause2 == null) || - !cause2.getMessage().startsWith( - "Absolute path required for library value:")) { - // rethrow - throw (ProviderException) cause; - } - System.out.println("Caught expected Exception: \n" + cause2); + Provider p = PKCS11Test.getSunPKCS11(config); + if (p == null) { + System.out.println("Skipping test - no PKCS11 provider available"); + } + } catch (InvalidParameterException ipe) { + Throwable ex = ipe.getCause(); + if (ex.getMessage().indexOf( + "Absolute path required for library value:") != -1) { + System.out.println("Test Passed: expected exception thrown"); + } else { + // rethrow + throw ipe; } } } diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/pkcs11/Provider/ConfigShortPath.java --- a/jdk/test/sun/security/pkcs11/Provider/ConfigShortPath.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/pkcs11/Provider/ConfigShortPath.java Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,44 +33,52 @@ public class ConfigShortPath { - private static final String[] configNames = { - "csp.cfg", "cspPlus.cfg", "cspSpace.cfg", "cspQuotedPath.cfg" + private static final String[] winConfigNames = { + "csp.cfg", "cspSpace.cfg", "cspQuotedPath.cfg" + }; + private static final String[] solConfigNames = { + "cspPlus.cfg" }; public static void main(String[] args) throws Exception { - Constructor cons = null; - try { - Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11"); - cons = clazz.getConstructor(String.class); - } catch (Exception ex) { - System.out.println("Skipping test - no PKCS11 provider available"); - return; + Provider p = Security.getProvider("SunPKCS11"); + if (p == null) { + // re-try w/ SunPKCS11-Solaris + p = Security.getProvider("SunPKCS11-Solaris"); + if (p == null) { + System.out.println("Skipping test - no PKCS11 provider available"); + return; + } } + + String osInfo = System.getProperty("os.name", ""); + String[] configNames = (osInfo.contains("Windows")? + winConfigNames : solConfigNames); + String testSrc = System.getProperty("test.src", "."); for (int i = 0; i < configNames.length; i++) { String configFile = testSrc + File.separator + configNames[i]; System.out.println("Testing against " + configFile); try { - Object obj = cons.newInstance(configFile); - } catch (InvocationTargetException ite) { - Throwable cause = ite.getCause(); - System.out.println(cause); - if (cause instanceof ProviderException) { - while ((cause = cause.getCause()) != null) { - System.out.println(cause); - String causeMsg = cause.getMessage(); - // Indicate failure if due to parsing config - if (causeMsg.indexOf("Unexpected") != -1) { - throw (ProviderException) cause; - } + p.configure(configFile); + } catch (InvalidParameterException ipe) { + ipe.printStackTrace(); + Throwable cause = ipe.getCause(); + // Indicate failure if due to parsing config + if (cause.getClass().getName().equals + ("sun.security.pkcs11.ConfigurationException")) { + // Error occurred during parsing + if (cause.getMessage().indexOf("Unexpected") != -1) { + throw (ProviderException) cause; } - // Consider the test passes if the exception is - // thrown after parsing, i.e. due to the absolute - // path requirement or the non-existent path. - } else { - // unexpected exception - throw new RuntimeException("Unexpected Exception", cause); + } + } catch (ProviderException pe) { + pe.printStackTrace(); + if (pe.getCause() instanceof IOException) { + // Thrown when the directory does not exist which is ok + System.out.println("Pass: config parsed ok"); + continue; } } } diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/pkcs11/Provider/cspSpace.cfg --- a/jdk/test/sun/security/pkcs11/Provider/cspSpace.cfg Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/pkcs11/Provider/cspSpace.cfg Tue Sep 08 15:39:51 2015 -0700 @@ -1,5 +1,3 @@ showInfo = false name = test library = C:\pki DLL\x64\acpkcs211.dll - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/rsa/SignatureOffsets.java --- a/jdk/test/sun/security/rsa/SignatureOffsets.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/rsa/SignatureOffsets.java Tue Sep 08 15:39:51 2015 -0700 @@ -50,4 +50,4 @@ InvalidKeyException, SignatureException { Offsets.main(args); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/ssl/StatusStapling/TestCase.java --- a/jdk/test/sun/security/ssl/StatusStapling/TestCase.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/ssl/StatusStapling/TestCase.java Tue Sep 08 15:39:51 2015 -0700 @@ -28,5 +28,3 @@ public interface TestCase { Map.Entry runTest(); } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/ssl/StatusStapling/TestUtils.java --- a/jdk/test/sun/security/ssl/StatusStapling/TestUtils.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/ssl/StatusStapling/TestUtils.java Tue Sep 08 15:39:51 2015 -0700 @@ -122,5 +122,3 @@ return resultBuf; } } - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/ssl/rsa/SignatureOffsets.java --- a/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java Tue Sep 08 15:39:51 2015 -0700 @@ -47,4 +47,4 @@ InvalidKeyException, SignatureException { Offsets.main(args); } -} \ No newline at end of file +} diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/tools/jarsigner/collator.sh --- a/jdk/test/sun/security/tools/jarsigner/collator.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/tools/jarsigner/collator.sh Tue Sep 08 15:39:51 2015 -0700 @@ -72,5 +72,3 @@ echo "ERR is $ERR" exit 1 fi - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/tools/jarsigner/jvindex.sh --- a/jdk/test/sun/security/tools/jarsigner/jvindex.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/tools/jarsigner/jvindex.sh Tue Sep 08 15:39:51 2015 -0700 @@ -72,5 +72,3 @@ echo "ERR is $ERR" exit 1 fi - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/tools/jarsigner/warnings.sh --- a/jdk/test/sun/security/tools/jarsigner/warnings.sh Tue Sep 01 12:57:41 2015 +0300 +++ b/jdk/test/sun/security/tools/jarsigner/warnings.sh Tue Sep 08 15:39:51 2015 -0700 @@ -115,5 +115,3 @@ echo "ERR is $ERR" exit 1 fi - - diff -r 23b29549f8d1 -r 54fbe836fcf0 jdk/test/sun/security/x509/X509CertImpl/V3Certificate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/x509/X509CertImpl/V3Certificate.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import static java.lang.System.out; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import sun.misc.BASE64Encoder; +import sun.security.util.BitArray; +import sun.security.util.ObjectIdentifier; +import sun.security.x509.*; + +/** + * @test + * @bug 8049237 + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * java.base/sun.misc + * @summary This test generates V3 certificate with all the supported + * extensions. Writes back the generated certificate in to a file and checks for + * equality with the original certificate. + */ +public class V3Certificate { + + public static final String V3_FILE = "certV3"; + public static final String V3_B64_FILE = "certV3.b64"; + + public static void main(String[] args) throws IOException, + NoSuchAlgorithmException, InvalidKeyException, CertificateException, + NoSuchProviderException, SignatureException { + + boolean success = true; + + success &= test("RSA", "SHA256withRSA", 2048); + success &= test("DSA", "SHA256withDSA", 2048); + success &= test("EC", "SHA256withECDSA", 384); + + if (!success) { + throw new RuntimeException("At least one test case failed"); + } + } + + public static boolean test(String algorithm, String sigAlg, int keyLength) + throws IOException, + NoSuchAlgorithmException, + InvalidKeyException, + CertificateException, + NoSuchProviderException, + SignatureException { + + byte[] issuerId = {1, 2, 3, 4, 5}; + byte[] subjectId = {6, 7, 8, 9, 10}; + boolean testResult = true; + + // Subject and Issuer + X500Name subject = new X500Name("test", "Oracle", "Santa Clara", + "US"); + X500Name issuer = subject; + + // Generate keys and sign + KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm); + keyGen.initialize(keyLength); + KeyPair pair = keyGen.generateKeyPair(); + PublicKey publicKey = pair.getPublic(); + PrivateKey privateKey = pair.getPrivate(); + MessageDigest md = MessageDigest.getInstance("SHA"); + byte[] keyId = md.digest(publicKey.getEncoded()); + + Signature signature = Signature.getInstance(sigAlg); + signature.initSign(privateKey); + + // Validity interval + Date firstDate = new Date(); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); + cal.set(2014, 03, 10, 12, 30, 30); + Date lastDate = cal.getTime(); + CertificateValidity interval = new CertificateValidity(firstDate, + lastDate); + + // Certificate Info + X509CertInfo cert = new X509CertInfo(); + + cert.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + cert.set(X509CertInfo.SERIAL_NUMBER, + new CertificateSerialNumber((int) (firstDate.getTime() / 1000))); + cert.set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(AlgorithmId.get(sigAlg))); + cert.set(X509CertInfo.SUBJECT, subject); + cert.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); + cert.set(X509CertInfo.VALIDITY, interval); + cert.set(X509CertInfo.ISSUER, issuer); + + cert.set(X509CertInfo.ISSUER_ID, + new UniqueIdentity( + new BitArray(issuerId.length * 8 - 2, issuerId))); + cert.set(X509CertInfo.SUBJECT_ID, new UniqueIdentity(subjectId)); + + // Create Extensions + CertificateExtensions exts = new CertificateExtensions(); + + GeneralNameInterface mailInf = new RFC822Name("test@Oracle.com"); + GeneralName mail = new GeneralName(mailInf); + GeneralNameInterface dnsInf = new DNSName("Oracle.com"); + GeneralName dns = new GeneralName(dnsInf); + GeneralNameInterface uriInf = new URIName("http://www.Oracle.com"); + GeneralName uri = new GeneralName(uriInf); + + // localhost + byte[] address = new byte[]{127, 0, 0, 1}; + + GeneralNameInterface ipInf = new IPAddressName(address); + GeneralName ip = new GeneralName(ipInf); + int[] oidData = new int[]{1, 2, 3, 4}; + + GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData)); + GeneralName oid = new GeneralName(oidInf); + + SubjectAlternativeNameExtension subjectName + = new SubjectAlternativeNameExtension(); + IssuerAlternativeNameExtension issuerName + = new IssuerAlternativeNameExtension(); + + GeneralNames subjectNames + = (GeneralNames) subjectName. + get(SubjectAlternativeNameExtension.SUBJECT_NAME); + + GeneralNames issuerNames + = (GeneralNames) issuerName. + get(IssuerAlternativeNameExtension.ISSUER_NAME); + + subjectNames.add(mail); + subjectNames.add(dns); + subjectNames.add(uri); + + issuerNames.add(ip); + issuerNames.add(oid); + + cal.set(2000, 11, 15, 12, 30, 30); + lastDate = cal.getTime(); + PrivateKeyUsageExtension pkusage + = new PrivateKeyUsageExtension(firstDate, lastDate); + + KeyUsageExtension usage = new KeyUsageExtension(); + usage.set(KeyUsageExtension.CRL_SIGN, true); + usage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true); + usage.set(KeyUsageExtension.NON_REPUDIATION, true); + + KeyIdentifier kid = new KeyIdentifier(keyId); + SerialNumber sn = new SerialNumber(42); + AuthorityKeyIdentifierExtension aki + = new AuthorityKeyIdentifierExtension(kid, subjectNames, sn); + + SubjectKeyIdentifierExtension ski + = new SubjectKeyIdentifierExtension(keyId); + + BasicConstraintsExtension cons + = new BasicConstraintsExtension(true, 10); + + PolicyConstraintsExtension pce = new PolicyConstraintsExtension(2, 4); + + exts.set(SubjectAlternativeNameExtension.NAME, subjectName); + exts.set(IssuerAlternativeNameExtension.NAME, issuerName); + exts.set(PrivateKeyUsageExtension.NAME, pkusage); + exts.set(KeyUsageExtension.NAME, usage); + exts.set(AuthorityKeyIdentifierExtension.NAME, aki); + exts.set(SubjectKeyIdentifierExtension.NAME, ski); + exts.set(BasicConstraintsExtension.NAME, cons); + exts.set(PolicyConstraintsExtension.NAME, pce); + cert.set(X509CertInfo.EXTENSIONS, exts); + + // Generate and sign X509CertImpl + X509CertImpl crt = new X509CertImpl(cert); + crt.sign(privateKey, sigAlg); + crt.verify(publicKey); + + try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE)); + FileOutputStream fos_b64 + = new FileOutputStream(new File(V3_B64_FILE)); + PrintWriter pw = new PrintWriter(fos_b64)) { + crt.encode((OutputStream) fos); + fos.flush(); + + // Certificate boundaries/ + pw.println("-----BEGIN CERTIFICATE-----"); + pw.flush(); + new BASE64Encoder().encodeBuffer(crt.getEncoded(), fos_b64); + fos_b64.flush(); + pw.println("-----END CERTIFICATE-----"); + } + + out.println("*** Certificate ***"); + out.println(crt); + out.println("*** End Certificate ***"); + + X509Certificate x2 = generateCertificate(V3_FILE); + if (!x2.equals(crt)) { + out.println("*** Certificate mismatch ***"); + testResult = false; + } + + X509Certificate x3 = generateCertificate(V3_B64_FILE); + if (!x3.equals(crt)) { + out.println("*** Certificate mismatch ***"); + testResult = false; + } + + return testResult; + } + + static X509Certificate generateCertificate(String certFile) { + try (InputStream inStrm = new FileInputStream(certFile)) { + CertificateFactory cf = CertificateFactory.getInstance("X509"); + X509Certificate x2 + = (X509Certificate) cf.generateCertificate(inStrm); + return x2; + } catch (CertificateException | IOException e) { + throw new RuntimeException("Exception while " + + "genrating certificate for " + certFile, e); + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/.hgtags --- a/langtools/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -322,3 +322,4 @@ 6ec3d5cb1bfcfba135c8d18866e567f1b1ada861 jdk9-b77 7fd155b7041c8aba7084f03e2fd1d6f74cceda75 jdk9-b78 eaab8a16dcfb807acacdb6d133f3ecd502667a8c jdk9-b79 +c5671e662392df372b2005b75afa6cfdc0eebce7 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Tue Sep 08 15:39:51 2015 -0700 @@ -76,7 +76,7 @@ private final AtomicBoolean used = new AtomicBoolean(); private Iterable processors; - JavacTaskImpl(Context context) { + protected JavacTaskImpl(Context context) { super(context, true); args = Arguments.instance(context); fileManager = context.get(JavaFileManager.class); diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/MultiTaskListener.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/MultiTaskListener.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/MultiTaskListener.java Tue Sep 08 15:39:51 2015 -0700 @@ -47,6 +47,9 @@ /** The context key for the MultiTaskListener. */ public static final Context.Key taskListenerKey = new Context.Key<>(); + /** Empty array of task listeners */ + private static final TaskListener[] EMPTY_LISTENERS = new TaskListener[0]; + /** Get the MultiTaskListener instance for this context. */ public static MultiTaskListener instance(Context context) { MultiTaskListener instance = context.get(taskListenerKey); @@ -64,7 +67,7 @@ * The current set of registered listeners. * This is a mutable reference to an immutable array. */ - TaskListener[] listeners = { }; + TaskListener[] listeners = EMPTY_LISTENERS; ClientCodeWrapper ccw; @@ -73,7 +76,7 @@ } public boolean isEmpty() { - return (listeners.length == 0); + return listeners == EMPTY_LISTENERS; } public void add(TaskListener listener) { @@ -88,10 +91,14 @@ public void remove(TaskListener listener) { for (int i = 0; i < listeners.length; i++) { if (ccw.unwrap(listeners[i]) == listener) { - TaskListener[] newListeners = new TaskListener[listeners.length - 1]; - System.arraycopy(listeners, 0, newListeners, 0, i); - System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i); - listeners = newListeners; + if (listeners.length == 1) { + listeners = EMPTY_LISTENERS; + } else { + TaskListener[] newListeners = new TaskListener[listeners.length - 1]; + System.arraycopy(listeners, 0, newListeners, 0, i); + System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i); + listeners = newListeners; + } break; } } @@ -117,4 +124,8 @@ public String toString() { return Arrays.toString(listeners); } + + public void clear() { + listeners = EMPTY_LISTENERS; + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,6 +26,7 @@ package com.sun.tools.javac.code; import com.sun.tools.javac.code.Kinds.Kind; +import java.lang.ref.WeakReference; import java.util.*; import java.util.function.BiConsumer; import java.util.stream.Stream; @@ -162,15 +163,49 @@ /** A list of scopes to be notified if items are to be removed from this scope. */ - List listeners = List.nil(); + ScopeListenerList listeners = new ScopeListenerList(); - public void addScopeListener(ScopeListener sl) { - listeners = listeners.prepend(sl); + public interface ScopeListener { + void symbolAdded(Symbol sym, Scope s); + void symbolRemoved(Symbol sym, Scope s); } - public interface ScopeListener { - public void symbolAdded(Symbol sym, Scope s); - public void symbolRemoved(Symbol sym, Scope s); + /** + * A list of scope listeners; listeners are stored in weak references, to avoid memory leaks. + * When the listener list is scanned (upon notification), elements corresponding to GC-ed + * listeners are removed so that the listener list size is kept in check. + */ + public static class ScopeListenerList { + + List> listeners = List.nil(); + + void add(ScopeListener sl) { + listeners = listeners.prepend(new WeakReference<>(sl)); + } + + void symbolAdded(Symbol sym, Scope scope) { + walkReferences(sym, scope, false); + } + + void symbolRemoved(Symbol sym, Scope scope) { + walkReferences(sym, scope, true); + } + + private void walkReferences(Symbol sym, Scope scope, boolean isRemove) { + ListBuffer> newListeners = new ListBuffer<>(); + for (WeakReference wsl : listeners) { + ScopeListener sl = wsl.get(); + if (sl != null) { + if (isRemove) { + sl.symbolRemoved(sym, scope); + } else { + sl.symbolAdded(sym, scope); + } + newListeners.add(wsl); + } + } + listeners = newListeners.toList(); + } } public enum LookupKind { @@ -404,9 +439,7 @@ elems = e; //notify listeners - for (List l = listeners; l.nonEmpty(); l = l.tail) { - l.head.symbolAdded(sym, this); - } + listeners.symbolAdded(sym, this); } /** Remove symbol from this scope. @@ -442,9 +475,7 @@ } //notify listeners - for (List l = listeners; l.nonEmpty(); l = l.tail) { - l.head.symbolRemoved(sym, this); - } + listeners.symbolRemoved(sym, this); } /** Enter symbol sym in this scope if not already there. @@ -698,11 +729,12 @@ finalized.enter(sym); } - finalized.addScopeListener(new ScopeListener() { + finalized.listeners.add(new ScopeListener() { @Override public void symbolAdded(Symbol sym, Scope s) { Assert.error("The scope is sealed."); } + @Override public void symbolRemoved(Symbol sym, Scope s) { Assert.error("The scope is sealed."); @@ -929,26 +961,20 @@ public void prependSubScope(Scope that) { if (that != null) { subScopes = subScopes.prepend(that); - that.addScopeListener(this); + that.listeners.add(this); mark++; - for (ScopeListener sl : listeners) { - sl.symbolAdded(null, this); //propagate upwards in case of nested CompoundScopes - } + listeners.symbolAdded(null, this); } } public void symbolAdded(Symbol sym, Scope s) { mark++; - for (ScopeListener sl : listeners) { - sl.symbolAdded(sym, s); - } + listeners.symbolAdded(sym, s); } public void symbolRemoved(Symbol sym, Scope s) { mark++; - for (ScopeListener sl : listeners) { - sl.symbolRemoved(sym, s); - } + listeners.symbolRemoved(sym, s); } public int getMark() { diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Tue Sep 08 15:39:51 2015 -0700 @@ -68,7 +68,7 @@ /** * The context key for the arguments. */ - protected static final Context.Key argsKey = new Context.Key<>(); + public static final Context.Key argsKey = new Context.Key<>(); private String ownName; private Set classNames; diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Sep 08 15:39:51 2015 -0700 @@ -87,7 +87,7 @@ */ public class JavaCompiler { /** The context key for the compiler. */ - protected static final Context.Key compilerKey = new Context.Key<>(); + public static final Context.Key compilerKey = new Context.Key<>(); /** Get the JavaCompiler instance for this context. */ public static JavaCompiler instance(Context context) { @@ -821,7 +821,7 @@ // as a JavaCompiler can only be used once, throw an exception if // it has been used before. if (hasBeenUsed) - throw new AssertionError("attempt to reuse JavaCompiler"); + checkReusable(); hasBeenUsed = true; // forcibly set the equivalent of -Xlint:-options, so that no further @@ -898,6 +898,10 @@ } } + protected void checkReusable() { + throw new AssertionError("attempt to reuse JavaCompiler"); + } + /** * Set needRootClasses to true, in JavaCompiler subclass constructor * that want to collect public apis of classes supplied on the command line. diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,6 +26,7 @@ package com.sun.tools.javac.parser; import java.util.*; +import java.util.stream.Collectors; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; @@ -510,7 +511,7 @@ if (mods != 0) { long lowestMod = mods & -mods; error(token.pos, "mod.not.allowed.here", - Flags.asFlagSet(lowestMod)); + Flags.asFlagSet(lowestMod)); } } @@ -946,10 +947,7 @@ t = odStack[0]; if (t.hasTag(JCTree.Tag.PLUS)) { - StringBuilder buf = foldStrings(t); - if (buf != null) { - t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString())); - } + t = foldStrings(t); } odStackSupply.add(odStack); @@ -973,37 +971,76 @@ /** If tree is a concatenation of string literals, replace it * by a single literal representing the concatenated string. */ - protected StringBuilder foldStrings(JCTree tree) { + protected JCExpression foldStrings(JCExpression tree) { if (!allowStringFolding) return null; - List buf = List.nil(); + ListBuffer opStack = new ListBuffer<>(); + ListBuffer litBuf = new ListBuffer<>(); + boolean needsFolding = false; + JCExpression curr = tree; while (true) { - if (tree.hasTag(LITERAL)) { - JCLiteral lit = (JCLiteral) tree; - if (lit.typetag == TypeTag.CLASS) { - StringBuilder sbuf = - new StringBuilder((String)lit.value); - while (buf.nonEmpty()) { - sbuf.append(buf.head); - buf = buf.tail; - } - return sbuf; - } - } else if (tree.hasTag(JCTree.Tag.PLUS)) { - JCBinary op = (JCBinary)tree; - if (op.rhs.hasTag(LITERAL)) { - JCLiteral lit = (JCLiteral) op.rhs; - if (lit.typetag == TypeTag.CLASS) { - buf = buf.prepend((String) lit.value); - tree = op.lhs; - continue; - } - } + if (curr.hasTag(JCTree.Tag.PLUS)) { + JCBinary op = (JCBinary)curr; + needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false); + curr = op.lhs; + } else { + needsFolding |= foldIfNeeded(curr, litBuf, opStack, true); + break; //last one! } - return null; + } + if (needsFolding) { + List ops = opStack.toList(); + JCExpression res = ops.head; + for (JCExpression op : ops.tail) { + res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op); + storeEnd(res, getEndPos(op)); + } + return res; + } else { + return tree; } } + private boolean foldIfNeeded(JCExpression tree, ListBuffer litBuf, + ListBuffer opStack, boolean last) { + JCLiteral str = stringLiteral(tree); + if (str != null) { + litBuf.prepend(str); + return last && merge(litBuf, opStack); + } else { + boolean res = merge(litBuf, opStack); + litBuf.clear(); + opStack.prepend(tree); + return res; + } + } + + boolean merge(ListBuffer litBuf, ListBuffer opStack) { + if (litBuf.isEmpty()) { + return false; + } else if (litBuf.size() == 1) { + opStack.prepend(litBuf.first()); + return false; + } else { + JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS, + litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining())); + storeEnd(t, litBuf.last().getEndPosition(endPosTable)); + opStack.prepend(t); + return true; + } + } + + private JCLiteral stringLiteral(JCTree tree) { + if (tree.hasTag(LITERAL)) { + JCLiteral lit = (JCLiteral)tree; + if (lit.typetag == TypeTag.CLASS) { + return lit; + } + } + return null; + } + + /** optimization: To save allocating a new operand/operator stack * for every binary operation, we use supplys. */ diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Tue Sep 08 15:39:51 2015 -0700 @@ -119,7 +119,7 @@ * or * {@literal Key -> Factory } */ - private final Map,Object> ht = new HashMap<>(); + protected final Map,Object> ht = new HashMap<>(); /** Set the factory for the key in this context. */ public void put(Key key, Factory fac) { @@ -173,7 +173,7 @@ */ private final Map, Key> kt = new HashMap<>(); - private Key key(Class clss) { + protected Key key(Class clss) { checkState(kt); Key k = uncheckedCast(kt.get(clss)); if (k == null) { diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Tue Sep 08 15:39:51 2015 -0700 @@ -334,7 +334,7 @@ * error message more than once. For each error, a pair consisting of the * source file name and source code position of the error is added to the set. */ - private Set> recorded = new HashSet<>(); + protected Set> recorded = new HashSet<>(); public boolean hasDiagnosticListener() { return diagListener != null; diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/Diagnostics/6769027/T6769027.java --- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java Tue Sep 08 15:39:51 2015 -0700 @@ -25,26 +25,19 @@ * @test * @bug 6769027 8006694 * @summary Source line should be displayed immediately after the first diagnostic line - * temporarily workaround combo tests are causing time out in several platforms - * @author Maurizio Cimadamore - * @library ../../lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest * @run main/othervm T6769027 */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +// use /othervm to avoid locale issues import java.net.URI; import java.util.regex.Matcher; import javax.tools.*; import com.sun.tools.javac.util.*; -public class T6769027 - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class T6769027 { enum OutputKind { RAW("rawDiagnostics","rawDiagnostics"), @@ -324,11 +317,6 @@ } @Override - protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) { - return outWriter; - } - - @Override protected boolean shouldReport(JavaFileObject jfo, int pos) { return true; } @@ -368,7 +356,6 @@ this.subdiagsIndent = subdiagsIndent; } - @Override public void run() { Context ctx = new Context(); Options options = Options.instance(ctx); @@ -419,7 +406,7 @@ for (IndentKind detailsIndent : IndentKind.values()) { for (IndentKind sourceIndent : IndentKind.values()) { for (IndentKind subdiagsIndent : IndentKind.values()) { - pool.execute(new T6769027(outputKind, + new T6769027(outputKind, errKind, multiKind, multiPolicy, @@ -431,7 +418,7 @@ summaryIndent, detailsIndent, sourceIndent, - subdiagsIndent)); + subdiagsIndent).run(); } } } @@ -445,8 +432,6 @@ } } } - - checkAfterExec(false); } void printInfo(String msg, String errorLine) { @@ -457,11 +442,11 @@ " caret=" + caretKind + " sourcePosition=" + sourceLineKind + " summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent + " sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent; - errWriter.println(sep); - errWriter.println(desc); - errWriter.println(sep); - errWriter.println(msg); - errWriter.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine); + System.err.println(sep); + System.err.println(desc); + System.err.println(sep); + System.err.println(msg); + System.err.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine); } void checkOutput(String msg) { @@ -494,8 +479,8 @@ } if (!msg.equals(errorLine)) { -// printInfo(msg, errorLine); - errCount.incrementAndGet(); + printInfo(msg, errorLine); + throw new AssertionError("errors were found"); } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/T7093325.java --- a/langtools/test/tools/javac/T7093325.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/T7093325.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,38 +23,41 @@ /* * @test - * @bug 7093325 8006694 + * @bug 7093325 8006694 8129962 * @summary Redundant entry in bytecode exception table * temporarily workaround combo tests are causing time out in several platforms - * @library lib + * @library /tools/javac/lib * @modules jdk.jdeps/com.sun.tools.classfile - * @build JavacTestingAbstractThreadedTest - * @run main/othervm T7093325 + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main T7093325 */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; +import java.io.InputStream; -import java.io.File; -import java.net.URI; -import java.util.Arrays; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; - -import com.sun.source.util.JavacTask; import com.sun.tools.classfile.Attribute; import com.sun.tools.classfile.ClassFile; import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool.*; +import com.sun.tools.classfile.ConstantPoolException; import com.sun.tools.classfile.Method; -public class T7093325 - extends JavacTestingAbstractThreadedTest - implements Runnable { +import javax.tools.JavaFileObject; - enum StatementKind { +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + +public class T7093325 extends ComboInstance { + + enum StatementKind implements ComboParameter { + NONE(null, false, false), THROW("throw new RuntimeException();", false, false), RETURN_NONEMPTY("System.out.println(); return;", true, false), RETURN_EMPTY("return;", true, true), @@ -64,107 +67,79 @@ boolean canInline; boolean empty; - private StatementKind(String stmt, boolean canInline, boolean empty) { + StatementKind(String stmt, boolean canInline, boolean empty) { this.stmt = stmt; this.canInline = canInline; this.empty = empty; } + + @Override + public String expand(String optParameter) { + return stmt; + } } - enum CatchArity { + enum CatchArity implements ComboParameter { NONE(""), - ONE("catch (A a) { #S1 }"), - TWO("catch (B b) { #S2 }"), - THREE("catch (C c) { #S3 }"), - FOUR("catch (D d) { #S4 }"); + ONE("catch (A a) { #{STMT[1]} }"), + TWO("catch (B b) { #{STMT[2]} }"), + THREE("catch (C c) { #{STMT[3]} }"), + FOUR("catch (D d) { #{STMT[4]} }"); String catchStr; - private CatchArity(String catchStr) { + CatchArity(String catchStr) { this.catchStr = catchStr; } - String catchers() { + @Override + public String expand(String optParameter) { if (this.ordinal() == 0) { return catchStr; } else { - return CatchArity.values()[this.ordinal() - 1].catchers() + + return CatchArity.values()[this.ordinal() - 1].expand(optParameter) + catchStr; } } } public static void main(String... args) throws Exception { - for (CatchArity ca : CatchArity.values()) { - for (StatementKind stmt0 : StatementKind.values()) { - if (ca.ordinal() == 0) { - pool.execute(new T7093325(ca, stmt0)); - continue; - } - for (StatementKind stmt1 : StatementKind.values()) { - if (ca.ordinal() == 1) { - pool.execute(new T7093325(ca, stmt0, stmt1)); - continue; - } - for (StatementKind stmt2 : StatementKind.values()) { - if (ca.ordinal() == 2) { - pool.execute(new T7093325(ca, stmt0, stmt1, stmt2)); - continue; - } - for (StatementKind stmt3 : StatementKind.values()) { - if (ca.ordinal() == 3) { - pool.execute( - new T7093325(ca, stmt0, stmt1, stmt2, stmt3)); - continue; - } - for (StatementKind stmt4 : StatementKind.values()) { - if (ca.ordinal() == 4) { - pool.execute( - new T7093325(ca, stmt0, stmt1, - stmt2, stmt3, stmt4)); - continue; - } - for (StatementKind stmt5 : StatementKind.values()) { - pool.execute( - new T7093325(ca, stmt0, stmt1, stmt2, - stmt3, stmt4, stmt5)); - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withFilter(T7093325::testFilter) + .withDimension("CATCH", (x, ca) -> x.ca = ca, CatchArity.values()) + .withArrayDimension("STMT", (x, stmt, idx) -> x.stmts[idx] = stmt, 5, StatementKind.values()) + .run(T7093325::new); } /** instance decls **/ CatchArity ca; - StatementKind[] stmts; + StatementKind[] stmts = new StatementKind[5]; - public T7093325(CatchArity ca, StatementKind... stmts) { - this.ca = ca; - this.stmts = stmts; + boolean testFilter() { + int lastPos = ca.ordinal() + 1; + for (int i = 0; i < stmts.length ; i++) { + boolean shouldBeSet = i < lastPos; + boolean isSet = stmts[i] != StatementKind.NONE; + if (shouldBeSet != isSet) { + return false; + } + } + return true; } @Override - public void run() { - int id = checkCount.incrementAndGet(); - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - JavaSource source = new JavaSource(id); - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), null, - null, null, Arrays.asList(source)); - ct.call(); - verifyBytecode(source, id); + public void doWork() throws IOException { + verifyBytecode(newCompilationTask() + .withSourceFromTemplate(source_template) + .generate()); } - void verifyBytecode(JavaSource source, int id) { + void verifyBytecode(Result> result) { boolean lastInlined = false; boolean hasCode = false; int gapsCount = 0; - for (int i = 0; i < stmts.length ; i++) { + for (int i = 0; i < ca.ordinal() + 1 ; i++) { lastInlined = stmts[i].canInline; hasCode = hasCode || !stmts[i].empty; if (lastInlined && hasCode) { @@ -176,12 +151,11 @@ gapsCount++; } - File compiledTest = new File(String.format("Test%s.class", id)); - try { - ClassFile cf = ClassFile.read(compiledTest); + try (InputStream is = result.get().iterator().next().openInputStream()) { + ClassFile cf = ClassFile.read(is); if (cf == null) { - throw new Error("Classfile not found: " + - compiledTest.getName()); + fail("Classfile not found: " + result.compilationInfo()); + return; } Method test_method = null; @@ -193,7 +167,8 @@ } if (test_method == null) { - throw new Error("Method test() not found in class Test"); + fail("Method test() not found in class Test" + result.compilationInfo()); + return; } Code_attribute code = null; @@ -205,7 +180,8 @@ } if (code == null) { - throw new Error("Code attribute not found in method test()"); + fail("Code attribute not found in method test()"); + return; } int actualGapsCount = 0; @@ -217,54 +193,28 @@ } if (actualGapsCount != gapsCount) { - throw new Error("Bad exception table for test()\n" + + fail("Bad exception table for test()\n" + "expected gaps: " + gapsCount + "\n" + "found gaps: " + actualGapsCount + "\n" + - source); + result.compilationInfo()); + return; } - } catch (Exception e) { + } catch (IOException | ConstantPoolException e) { e.printStackTrace(); - throw new Error("error reading " + compiledTest +": " + e); + fail("error reading classfile: " + e); } } - class JavaSource extends SimpleJavaFileObject { - - static final String source_template = + static final String source_template = + "class Test {\n" + + " void test() {\n" + + " try { #{STMT[0]} } #{CATCH} finally { System.out.println(); }\n" + + " }\n" + + "}\n" + "class A extends RuntimeException {} \n" + "class B extends RuntimeException {} \n" + "class C extends RuntimeException {} \n" + "class D extends RuntimeException {} \n" + - "class E extends RuntimeException {} \n" + - "class Test#ID {\n" + - " void test() {\n" + - " try { #S0 } #C finally { System.out.println(); }\n" + - " }\n" + - "}"; - - String source; - - public JavaSource(int id) { - super(URI.create(String.format("myfo:/Test%s.java", id)), - JavaFileObject.Kind.SOURCE); - source = source_template.replace("#C", ca.catchers()); - source = source.replace("#S0", stmts[0].stmt); - source = source.replace("#ID", String.valueOf(id)); - for (int i = 1; i < ca.ordinal() + 1; i++) { - source = source.replace("#S" + i, stmts[i].stmt); - } - } - - @Override - public String toString() { - return source; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - + "class E extends RuntimeException {}"; } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/TestBootstrapMethodsCount.java --- a/langtools/test/tools/javac/TestBootstrapMethodsCount.java Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8129547 - * @summary Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs - * @library lib - * @modules jdk.jdeps/com.sun.tools.classfile - * jdk.compiler/com.sun.tools.javac.api - * jdk.compiler/com.sun.tools.javac.code - * jdk.compiler/com.sun.tools.javac.jvm - * jdk.compiler/com.sun.tools.javac.tree - * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm TestBootstrapMethodsCount - */ - -import java.io.File; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; - -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.util.TaskEvent; -import com.sun.source.util.TaskListener; -import com.sun.source.util.TreeScanner; - -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.BootstrapMethods_attribute; -import com.sun.tools.classfile.ClassFile; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Symtab; -import com.sun.tools.javac.code.Types; -import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.tree.JCTree.JCIdent; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Names; - -import static com.sun.tools.javac.jvm.ClassFile.*; - -public class TestBootstrapMethodsCount - extends JavacTestingAbstractThreadedTest - implements Runnable { - - - public static void main(String... args) throws Exception { - pool.execute(new TestBootstrapMethodsCount()); - checkAfterExec(); - } - - DiagChecker dc; - - TestBootstrapMethodsCount() { - dc = new DiagChecker(); - } - - public void run() { - int id = checkCount.incrementAndGet(); - JavaSource source = new JavaSource(id); - JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc, - Arrays.asList("-g"), null, Arrays.asList(source)); - Context context = ct.getContext(); - Symtab syms = Symtab.instance(context); - Names names = Names.instance(context); - Types types = Types.instance(context); - ct.addTaskListener(new Indifier(syms, names, types)); - try { - ct.generate(); - } catch (Throwable t) { - t.printStackTrace(); - throw new AssertionError( - String.format("Error thrown when compiling following code\n%s", - source.source)); - } - if (dc.diagFound) { - throw new AssertionError( - String.format("Diags found when compiling following code\n%s\n\n%s", - source.source, dc.printDiags())); - } - verifyBytecode(id); - } - - void verifyBytecode(int id) { - File compiledTest = new File(String.format("Test%d.class", id)); - try { - ClassFile cf = ClassFile.read(compiledTest); - BootstrapMethods_attribute bsm_attr = - (BootstrapMethods_attribute)cf - .getAttribute(Attribute.BootstrapMethods); - int length = bsm_attr.bootstrap_method_specifiers.length; - if (length != 1) { - throw new Error("Bad number of method specifiers " + - "in BootstrapMethods attribute: " + length); - } - } catch (Exception e) { - e.printStackTrace(); - throw new Error("error reading " + compiledTest +": " + e); - } - } - - class JavaSource extends SimpleJavaFileObject { - - static final String source_template = "import java.lang.invoke.*;\n" + - "class Bootstrap {\n" + - " public static CallSite bsm(MethodHandles.Lookup lookup, " + - "String name, MethodType methodType) {\n" + - " return null;\n" + - " }\n" + - "}\n" + - "class Test#ID {\n" + - " void m1() { }\n" + - " void m2(Object arg1) { }\n" + - " void test1() {\n" + - " Object o = this; // marker statement \n" + - " m1();\n" + - " }\n" + - " void test2(Object arg1) {\n" + - " Object o = this; // marker statement \n" + - " m2(arg1);\n" + - " }\n" + - "}"; - - String source; - - JavaSource(int id) { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = source_template.replace("#ID", String.valueOf(id)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - class Indifier extends TreeScanner implements TaskListener { - - MethodSymbol bsm; - Symtab syms; - Names names; - Types types; - - Indifier(Symtab syms, Names names, Types types) { - this.syms = syms; - this.names = names; - this.types = types; - } - - @Override - public void started(TaskEvent e) { - //do nothing - } - - @Override - public void finished(TaskEvent e) { - if (e.getKind() == TaskEvent.Kind.ANALYZE) { - scan(e.getCompilationUnit(), null); - } - } - - @Override - public Void visitMethodInvocation(MethodInvocationTree node, Void p) { - super.visitMethodInvocation(node, p); - JCMethodInvocation apply = (JCMethodInvocation)node; - JCIdent ident = (JCIdent)apply.meth; - Symbol oldSym = ident.sym; - if (!oldSym.isConstructor()) { - ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, - oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]); - } - return null; - } - - @Override - public Void visitMethod(MethodTree node, Void p) { - super.visitMethod(node, p); - if (node.getName().toString().equals("bsm")) { - bsm = ((JCMethodDecl)node).sym; - } - return null; - } - } - - static class DiagChecker - implements javax.tools.DiagnosticListener { - - boolean diagFound; - ArrayList diags = new ArrayList<>(); - - public void report(Diagnostic diagnostic) { - diags.add(diagnostic.getMessage(Locale.getDefault())); - diagFound = true; - } - - String printDiags() { - StringBuilder buf = new StringBuilder(); - for (String s : diags) { - buf.append(s); - buf.append("\n"); - } - return buf.toString(); - } - } - -} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java --- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,53 +23,47 @@ /* * @test - * @bug 8002099 8006694 + * @bug 8002099 8006694 8129962 * @summary Add support for intersection types in cast expression * temporarily workaround combo tests are causing time out in several platforms - * @library ../../lib - * @modules jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm/timeout=360 IntersectionTypeCastTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + + * @run main IntersectionTypeCastTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import com.sun.tools.javac.util.List; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; +import java.io.IOException; -public class IntersectionTypeCastTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class IntersectionTypeCastTest extends ComboInstance { - interface Type { + interface Type extends ComboParameter { boolean subtypeOf(Type that); - String asString(); boolean isClass(); boolean isInterface(); } enum InterfaceKind implements Type { - A("interface A { }\n", "A", null), - B("interface B { }\n", "B", null), - C("interface C extends A { }\n", "C", A); + A("A", null), + B("B", null), + C("C", A); - String declStr; String typeStr; InterfaceKind superInterface; - InterfaceKind(String declStr, String typeStr, - InterfaceKind superInterface) { - this.declStr = declStr; + InterfaceKind(String typeStr, InterfaceKind superInterface) { this.typeStr = typeStr; this.superInterface = superInterface; } @@ -81,11 +75,6 @@ } @Override - public String asString() { - return typeStr; - } - - @Override public boolean isClass() { return false; } @@ -94,42 +83,31 @@ public boolean isInterface() { return true; } + + @Override + public String expand(String optParameter) { + return typeStr; + } } enum ClassKind implements Type { - OBJECT(null, "Object"), - CA("#M class CA implements A { }\n", "CA", - InterfaceKind.A), - CB("#M class CB implements B { }\n", "CB", - InterfaceKind.B), - CAB("#M class CAB implements A, B { }\n", "CAB", - InterfaceKind.A, InterfaceKind.B), - CC("#M class CC implements C { }\n", "CC", - InterfaceKind.C, InterfaceKind.A), - CCA("#M class CCA implements C, A { }\n", "CCA", - InterfaceKind.C, InterfaceKind.A), - CCB("#M class CCB implements C, B { }\n", "CCB", - InterfaceKind.C, InterfaceKind.A, InterfaceKind.B), - CCAB("#M class CCAB implements C, A, B { }\n", "CCAB", - InterfaceKind.C, InterfaceKind.A, InterfaceKind.B); + OBJECT("Object"), + CA("CA", InterfaceKind.A), + CB("CB", InterfaceKind.B), + CAB("CAB", InterfaceKind.A, InterfaceKind.B), + CC("CC", InterfaceKind.C, InterfaceKind.A), + CCA("CCA", InterfaceKind.C, InterfaceKind.A), + CCB("CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B), + CCAB("CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B); - String declTemplate; String typeStr; List superInterfaces; - ClassKind(String declTemplate, String typeStr, - InterfaceKind... superInterfaces) { - this.declTemplate = declTemplate; + ClassKind(String typeStr, InterfaceKind... superInterfaces) { this.typeStr = typeStr; this.superInterfaces = List.from(superInterfaces); } - String getDecl(ModifierKind mod) { - return declTemplate != null ? - declTemplate.replaceAll("#M", mod.modStr) : - ""; - } - @Override public boolean subtypeOf(Type that) { return this == that || superInterfaces.contains(that) || @@ -137,11 +115,6 @@ } @Override - public String asString() { - return typeStr; - } - - @Override public boolean isClass() { return true; } @@ -150,9 +123,14 @@ public boolean isInterface() { return false; } + + @Override + public String expand(String optParameter) { + return typeStr; + } } - enum ModifierKind { + enum ModifierKind implements ComboParameter { NONE(""), FINAL("final"); @@ -161,14 +139,18 @@ ModifierKind(String modStr) { this.modStr = modStr; } + + @Override + public String expand(String optParameter) { + return modStr; + } } - enum CastKind { - CLASS("(#C)", 0), - INTERFACE("(#I0)", 1), - INTERSECTION2("(#C & #I0)", 1), - INTERSECTION3("(#C & #I0 & #I1)", 2); - //INTERSECTION4("(#C & #I0 & #I1 & #I2)", 3); + enum CastKind implements ComboParameter { + CLASS("(#{CLAZZ#IDX})", 0), + INTERFACE("(#{INTF1#IDX})", 1), + INTERSECTION2("(#{CLAZZ#IDX} & #{INTF1#IDX})", 1), + INTERSECTION3("(#{CLAZZ#IDX} & #{INTF1#IDX} & #{INTF2#IDX})", 2); String castTemplate; int interfaceBounds; @@ -177,6 +159,11 @@ this.castTemplate = castTemplate; this.interfaceBounds = interfaceBounds; } + + @Override + public String expand(String optParameter) { + return castTemplate.replaceAll("#IDX", optParameter); + } } static class CastInfo { @@ -188,19 +175,9 @@ this.types = types; } - String getCast() { - String temp = kind.castTemplate.replaceAll("#C", - types[0].asString()); - for (int i = 0; i < kind.interfaceBounds ; i++) { - temp = temp.replace(String.format("#I%d", i), - types[i + 1].asString()); - } - return temp; - } - boolean hasDuplicateTypes() { - for (int i = 0 ; i < types.length ; i++) { - for (int j = 0 ; j < types.length ; j++) { + for (int i = 0 ; i < arity() ; i++) { + for (int j = 0 ; j < arity() ; j++) { if (i != j && types[i] == types[j]) { return true; } @@ -210,8 +187,10 @@ } boolean compatibleWith(ModifierKind mod, CastInfo that) { - for (Type t1 : types) { - for (Type t2 : that.types) { + for (int i = 0 ; i < arity() ; i++) { + Type t1 = types[i]; + for (int j = 0 ; j < that.arity() ; j++) { + Type t2 = that.types[j]; boolean compat = t1.subtypeOf(t2) || t2.subtypeOf(t1) || @@ -223,138 +202,92 @@ } return true; } + + private int arity() { + return kind.interfaceBounds + 1; + } } public static void main(String... args) throws Exception { - for (ModifierKind mod : ModifierKind.values()) { - for (CastInfo cast1 : allCastInfo()) { - for (CastInfo cast2 : allCastInfo()) { - pool.execute( - new IntersectionTypeCastTest(mod, cast1, cast2)); + new ComboTestHelper() + .withFilter(IntersectionTypeCastTest::isRedundantCast) + .withFilter(IntersectionTypeCastTest::arityFilter) + .withArrayDimension("CAST", (x, ck, idx) -> x.castKinds[idx] = ck, 2, CastKind.values()) + .withDimension("CLAZZ1", (x, ty) -> x.types1[0] = ty, ClassKind.values()) + .withDimension("INTF11", (x, ty) -> x.types1[1] = ty, InterfaceKind.values()) + .withDimension("INTF21", (x, ty) -> x.types1[2] = ty, InterfaceKind.values()) + .withDimension("CLAZZ2", (x, ty) -> x.types2[0] = ty, ClassKind.values()) + .withDimension("INTF12", (x, ty) -> x.types2[1] = ty, InterfaceKind.values()) + .withDimension("INTF22", (x, ty) -> x.types2[2] = ty, InterfaceKind.values()) + .withDimension("MOD", (x, mod) -> x.mod = mod, ModifierKind.values()) + .run(IntersectionTypeCastTest::new); + } + + boolean isRedundantCast() { + for (int i = 0 ; i < 2 ; i++) { + Type[] types = i == 0 ? types1 : types2; + if (castKinds[i] == CastKind.INTERFACE && types[0] != ClassKind.OBJECT) { + return false; + } + } + return true; + } + + boolean arityFilter() { + for (int i = 0 ; i < 2 ; i++) { + int lastPos = castKinds[i].interfaceBounds + 1; + Type[] types = i == 0 ? types1 : types2; + for (int j = 1; j < types.length; j++) { + boolean shouldBeSet = j < lastPos; + if (!shouldBeSet && (types[j] != InterfaceKind.A)) { + return false; } } } - checkAfterExec(); - } - - static List allCastInfo() { - ListBuffer buf = new ListBuffer<>(); - for (CastKind kind : CastKind.values()) { - for (ClassKind clazz : ClassKind.values()) { - if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) { - continue; - } else if (kind.interfaceBounds == 0) { - buf.append(new CastInfo(kind, clazz)); - continue; - } else { - for (InterfaceKind intf1 : InterfaceKind.values()) { - if (kind.interfaceBounds == 1) { - buf.append(new CastInfo(kind, clazz, intf1)); - continue; - } else { - for (InterfaceKind intf2 : InterfaceKind.values()) { - if (kind.interfaceBounds == 2) { - buf.append( - new CastInfo(kind, clazz, intf1, intf2)); - continue; - } else { - for (InterfaceKind intf3 : InterfaceKind.values()) { - buf.append( - new CastInfo(kind, clazz, intf1, - intf2, intf3)); - continue; - } - } - } - } - } - } - } - } - return buf.toList(); + return true; } ModifierKind mod; - CastInfo cast1, cast2; - JavaSource source; - DiagnosticChecker diagChecker; - - IntersectionTypeCastTest(ModifierKind mod, CastInfo cast1, CastInfo cast2) { - this.mod = mod; - this.cast1 = cast1; - this.cast2 = cast2; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); - } + CastKind[] castKinds = new CastKind[2]; + Type[] types1 = new Type[3]; + Type[] types2 = new Type[3]; @Override - public void run() { - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - throw new AssertionError("Error thrown when compiling the following code:\n" + - source.getCharContent(true)); - } - check(); + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(bodyTemplate) + .analyze()); } - class JavaSource extends SimpleJavaFileObject { - - String bodyTemplate = "class Test {\n" + - " void test() {\n" + - " Object o = #C1#C2null;\n" + - " } }"; - - String source = ""; + String bodyTemplate = "class Test {\n" + + " void test() {\n" + + " Object o = #{CAST[0].1}#{CAST[1].2}null;\n" + + " } }\n" + + "interface A { }\n" + + "interface B { }\n" + + "interface C extends A { }\n" + + "#{MOD} class CA implements A { }\n" + + "#{MOD} class CB implements B { }\n" + + "#{MOD} class CAB implements A, B { }\n" + + "#{MOD} class CC implements C { }\n" + + "#{MOD} class CCA implements C, A { }\n" + + "#{MOD} class CCB implements C, B { }\n" + + "#{MOD} class CCAB implements C, A, B { }"; - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - for (ClassKind ck : ClassKind.values()) { - source += ck.getDecl(mod); - } - for (InterfaceKind ik : InterfaceKind.values()) { - source += ik.declStr; - } - source += bodyTemplate.replaceAll("#C1", cast1.getCast()). - replaceAll("#C2", cast2.getCast()); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - void check() { - checkCount.incrementAndGet(); - + void check(Result res) { + CastInfo cast1 = new CastInfo(castKinds[0], types1); + CastInfo cast2 = new CastInfo(castKinds[1], types2); boolean errorExpected = cast1.hasDuplicateTypes() || cast2.hasDuplicateTypes(); errorExpected |= !cast2.compatibleWith(mod, cast1); - if (errorExpected != diagChecker.errorFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound error: " + diagChecker.errorFound + + boolean errorsFound = res.hasErrors(); + if (errorExpected != errorsFound) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound error: " + errorsFound + "\nExpected error: " + errorExpected); } } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java --- a/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,40 +23,41 @@ /* * @test - * @bug 8005166 + * @bug 8005166 8129962 * @summary Add support for static interface methods * Smoke test for static interface method hiding - * @modules jdk.compiler - * @run main/timeout=600 InterfaceMethodHidingTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main InterfaceMethodHidingTest */ -import com.sun.source.util.JavacTask; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; +import java.io.IOException; + +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - -public class InterfaceMethodHidingTest { - - static int checkCount = 0; +public class InterfaceMethodHidingTest extends ComboInstance { - enum SignatureKind { - VOID_INTEGER("void m(Integer s)", "return;"), - STRING_INTEGER("String m(Integer s)", "return null;"), - VOID_STRING("void m(String s)", "return;"), - STRING_STRING("String m(String s)", "return null;"); + enum SignatureKind implements ComboParameter { + VOID_INTEGER("void m(Integer s)", false), + STRING_INTEGER("String m(Integer s)", true), + VOID_STRING("void m(String s)", false), + STRING_STRING("String m(String s)", true); String sigStr; - String retStr; + boolean needsReturn; - SignatureKind(String sigStr, String retStr) { + SignatureKind(String sigStr, boolean needsReturn) { this.sigStr = sigStr; - this.retStr = retStr; + this.needsReturn = needsReturn; } boolean overrideEquivalentWith(SignatureKind s2) { @@ -71,18 +72,21 @@ throw new AssertionError("bad signature kind"); } } + + @Override + public String expand(String optParameter) { + return sigStr; + } } - enum MethodKind { - VIRTUAL("", "#M #S;"), - STATIC("static", "#M #S { #BE; #R }"), - DEFAULT("default", "#M #S { #BE; #R }"); + enum MethodKind implements ComboParameter { + VIRTUAL("#{SIG[#IDX]};"), + STATIC("static #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }"), + DEFAULT("default #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }"); - String modStr; String methTemplate; - MethodKind(String modStr, String methTemplate) { - this.modStr = modStr; + MethodKind(String methTemplate) { this.methTemplate = methTemplate; } @@ -96,15 +100,13 @@ mk1 != STATIC; } - String getBody(BodyExpr be, SignatureKind sk) { - return methTemplate.replaceAll("#BE", be.bodyExprStr) - .replaceAll("#R", sk.retStr) - .replaceAll("#M", modStr) - .replaceAll("#S", sk.sigStr); + @Override + public String expand(String optParameter) { + return methTemplate.replaceAll("#IDX", optParameter); } } - enum BodyExpr { + enum BodyExpr implements ComboParameter { NONE(""), THIS("Object o = this"); @@ -118,129 +120,78 @@ return this == NONE || mk != MethodKind.STATIC; } + + @Override + public String expand(String optParameter) { + return bodyExprStr; + } } public static void main(String... args) throws Exception { - - //create default shared JavaCompiler - reused across multiple compilations - JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); - try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { - - for (MethodKind mk1 : MethodKind.values()) { - for (SignatureKind sk1 : SignatureKind.values()) { - for (BodyExpr be1 : BodyExpr.values()) { - for (MethodKind mk2 : MethodKind.values()) { - for (SignatureKind sk2 : SignatureKind.values()) { - for (BodyExpr be2 : BodyExpr.values()) { - for (MethodKind mk3 : MethodKind.values()) { - for (SignatureKind sk3 : SignatureKind.values()) { - for (BodyExpr be3 : BodyExpr.values()) { - new InterfaceMethodHidingTest(mk1, mk2, mk3, sk1, sk2, sk3, be1, be2, be3).run(comp, fm); - } - } - } - } - } - } - } - } - } - System.out.println("Total check executed: " + checkCount); - } + new ComboTestHelper() + .withArrayDimension("SIG", (x, sig, idx) -> x.signatureKinds[idx] = sig, 3, SignatureKind.values()) + .withArrayDimension("BODY", (x, body, idx) -> x.bodyExprs[idx] = body, 3, BodyExpr.values()) + .withArrayDimension("MET", (x, meth, idx) -> x.methodKinds[idx] = meth, 3, MethodKind.values()) + .run(InterfaceMethodHidingTest::new); } - MethodKind mk1, mk2, mk3; - SignatureKind sk1, sk2, sk3; - BodyExpr be1, be2, be3; - JavaSource source; - DiagnosticChecker diagChecker; + MethodKind[] methodKinds = new MethodKind[3]; + SignatureKind[] signatureKinds = new SignatureKind[3]; + BodyExpr[] bodyExprs = new BodyExpr[3]; - InterfaceMethodHidingTest(MethodKind mk1, MethodKind mk2, MethodKind mk3, - SignatureKind sk1, SignatureKind sk2, SignatureKind sk3, BodyExpr be1, BodyExpr be2, BodyExpr be3) { - this.mk1 = mk1; - this.mk2 = mk2; - this.mk3 = mk3; - this.sk1 = sk1; - this.sk2 = sk2; - this.sk3 = sk3; - this.be1 = be1; - this.be2 = be2; - this.be3 = be3; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); - } - - class JavaSource extends SimpleJavaFileObject { - - String template = "interface Sup {\n" + + String template = "interface Sup {\n" + " default void sup() { }\n" + "}\n" + "interface A extends Sup {\n" + - " #M1\n" + + " #{MET[0].0}\n" + "}\n" + "interface B extends A, Sup {\n" + - " #M2\n" + + " #{MET[1].1}\n" + "}\n" + "interface C extends B, Sup {\n" + - " #M3\n" + + " #{MET[2].2}\n" + "}\n"; - String source; + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withOption("-XDallowStaticInterfaceMethods") + .withSourceFromTemplate(template, this::returnExpr) + .analyze()); + } - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#M1", mk1.getBody(be1, sk1)) - .replaceAll("#M2", mk2.getBody(be2, sk2)) - .replaceAll("#M3", mk3.getBody(be3, sk3)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + ComboParameter returnExpr(String name) { + switch (name) { + case "RET": + return optParameter -> { + int idx = new Integer(optParameter); + return signatureKinds[idx].needsReturn ? "return null;" : "return;"; + }; + default: + return null; } } - void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { - JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, - Arrays.asList("-XDallowStaticInterfaceMethods"), null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true)); - } - check(); - } + void check(Result res) { + boolean errorExpected = !bodyExprs[0].allowed(methodKinds[0]) || + !bodyExprs[1].allowed(methodKinds[1]) || + !bodyExprs[2].allowed(methodKinds[2]); - void check() { - boolean errorExpected = - !be1.allowed(mk1) || !be2.allowed(mk2) || !be3.allowed(mk3); - - if (mk1.inherithed()) { - errorExpected |= - sk2.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk2, sk2, mk1, sk1) || - sk3.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk3, sk3, mk1, sk1); + if (methodKinds[0].inherithed()) { + errorExpected |= signatureKinds[1].overrideEquivalentWith(signatureKinds[0]) && + !MethodKind.overrides(methodKinds[1], signatureKinds[1], methodKinds[0], signatureKinds[0]) || + signatureKinds[2].overrideEquivalentWith(signatureKinds[0]) && + !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[0], signatureKinds[0]); } - if (mk2.inherithed()) { - errorExpected |= - sk3.overrideEquivalentWith(sk2) && !MethodKind.overrides(mk3, sk3, mk2, sk2); + if (methodKinds[1].inherithed()) { + errorExpected |= signatureKinds[2].overrideEquivalentWith(signatureKinds[1]) && + !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[1], signatureKinds[1]); } - checkCount++; - if (diagChecker.errorFound != errorExpected) { - throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) + - "\nfound error: " + diagChecker.errorFound); - } - } - - static class DiagnosticChecker implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } + if (res.hasErrors() != errorExpected) { + fail("Problem when compiling source:\n" + res.compilationInfo() + + "\nfound error: " + res.hasErrors()); } } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java --- a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,33 +23,32 @@ /* * @test - * @bug 7192246 8006694 + * @bug 7192246 8006694 8129962 * @summary Automatic test for checking correctness of default super/this resolution * temporarily workaround combo tests are causing time out in several platforms - * @library ../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm TestDefaultSuperCall + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main TestDefaultSuperCall */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import java.net.URI; -import java.util.Arrays; +import java.io.IOException; import java.util.ArrayList; import java.util.List; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; - -import com.sun.source.util.JavacTask; -public class TestDefaultSuperCall - extends JavacTestingAbstractThreadedTest - implements Runnable { +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - enum InterfaceKind { +public class TestDefaultSuperCall extends ComboInstance { + + enum InterfaceKind implements ComboParameter { DEFAULT("interface A extends B { default void m() { } }"), ABSTRACT("interface A extends B { void m(); }"), NONE("interface A extends B { }"); @@ -63,9 +62,14 @@ boolean methodDefined() { return this == DEFAULT; } + + @Override + public String expand(String optParameter) { + return interfaceStr; + } } - enum PruneKind { + enum PruneKind implements ComboParameter { NO_PRUNE("interface C { }"), PRUNE("interface C extends A { }"); @@ -79,15 +83,20 @@ PruneKind(String interfaceStr) { this.interfaceStr = interfaceStr; } + + @Override + public String expand(String optParameter) { + return interfaceStr; + } } - enum QualifierKind { + enum QualifierKind implements ComboParameter { DIRECT_1("C"), DIRECT_2("A"), INDIRECT("B"), UNRELATED("E"), - ENCLOSING_1(null), - ENCLOSING_2(null); + ENCLOSING_1("name0"), + ENCLOSING_2("name1"); String qualifierStr; @@ -95,15 +104,6 @@ this.qualifierStr = qualifierStr; } - String getQualifier(Shape sh) { - switch (this) { - case ENCLOSING_1: return sh.enclosingAt(0); - case ENCLOSING_2: return sh.enclosingAt(1); - default: - return qualifierStr; - } - } - boolean isEnclosing() { return this == ENCLOSING_1 || this == ENCLOSING_2; @@ -119,9 +119,14 @@ return false; } } + + @Override + public String expand(String optParameter) { + return qualifierStr; + } } - enum ExprKind { + enum ExprKind implements ComboParameter { THIS("this"), SUPER("super"); @@ -130,19 +135,24 @@ ExprKind(String exprStr) { this.exprStr = exprStr; } + + @Override + public String expand(String optParameter) { + return exprStr; + } } - enum ElementKind { - INTERFACE("interface #N { #B }", true), - INTERFACE_EXTENDS("interface #N extends A, C { #B }", true), - CLASS("class #N { #B }", false), - CLASS_EXTENDS("abstract class #N implements A, C { #B }", false), - STATIC_CLASS("static class #N { #B }", true), - STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true), - ANON_CLASS("new Object() { #B };", false), - METHOD("void test() { #B }", false), - STATIC_METHOD("static void test() { #B }", true), - DEFAULT_METHOD("default void test() { #B }", false); + enum ElementKind implements ComboParameter { + INTERFACE("interface name#CURR { #BODY }", true), + INTERFACE_EXTENDS("interface name#CURR extends A, C { #BODY }", true), + CLASS("class name#CURR { #BODY }", false), + CLASS_EXTENDS("abstract class name#CURR implements A, C { #BODY }", false), + STATIC_CLASS("static class name#CURR { #BODY }", true), + STATIC_CLASS_EXTENDS("abstract static class name#CURR implements A, C { #BODY }", true), + ANON_CLASS("new Object() { #BODY };", false), + METHOD("void test() { #BODY }", false), + STATIC_METHOD("static void test() { #BODY }", true), + DEFAULT_METHOD("default void test() { #BODY }", false); String templateDecl; boolean isStatic; @@ -207,11 +217,21 @@ this == STATIC_CLASS_EXTENDS || this == CLASS_EXTENDS; } + + @Override + public String expand(String optParameter) { + int nextDepth = new Integer(optParameter) + 1; + String replStr = (nextDepth <= 4) ? + String.format("#{ELEM[%d].%d}", nextDepth, nextDepth) : + "#{QUAL}.#{EXPR}.#{METH}();"; + return templateDecl + .replaceAll("#CURR", optParameter) + .replaceAll("#BODY", replStr); + } } static class Shape { - String shapeStr; List enclosingElements; List enclosingNames; List elementsWithMethod; @@ -234,114 +254,73 @@ } else { elementsWithMethod.add(prevName); } - String element = ek.templateDecl.replaceAll("#N", name); - shapeStr = shapeStr == - null ? element : shapeStr.replaceAll("#B", element); prevName = name; } } - - String getShape(QualifierKind qk, ExprKind ek) { - String methName = ek == ExprKind.THIS ? "test" : "m"; - String call = qk.getQualifier(this) + "." + - ek.exprStr + "." + methName + "();"; - return shapeStr.replaceAll("#B", call); - } - - String enclosingAt(int index) { - return index < enclosingNames.size() ? - enclosingNames.get(index) : "BAD"; - } } public static void main(String... args) throws Exception { - for (InterfaceKind ik : InterfaceKind.values()) { - for (PruneKind pk : PruneKind.values()) { - for (ElementKind ek1 : ElementKind.values()) { - if (!ek1.isAllowedTop()) continue; - for (ElementKind ek2 : ElementKind.values()) { - if (!ek2.isAllowedEnclosing(ek1, true)) continue; - for (ElementKind ek3 : ElementKind.values()) { - if (!ek3.isAllowedEnclosing(ek2, false)) continue; - for (ElementKind ek4 : ElementKind.values()) { - if (!ek4.isAllowedEnclosing(ek3, false)) continue; - for (ElementKind ek5 : ElementKind.values()) { - if (!ek5.isAllowedEnclosing(ek4, false) || - ek5.isClassDecl()) continue; - for (QualifierKind qk : QualifierKind.values()) { - for (ExprKind ek : ExprKind.values()) { - pool.execute( - new TestDefaultSuperCall(ik, pk, - new Shape(ek1, ek2, ek3, - ek4, ek5), qk, ek)); - } - } - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withFilter(TestDefaultSuperCall::filterBadTopElement) + .withFilter(TestDefaultSuperCall::filterBadIntermediateElement) + .withFilter(TestDefaultSuperCall::filterBadTerminalElement) + .withDimension("INTF1", (x, ik) -> x.ik = ik, InterfaceKind.values()) + .withDimension("INTF2", (x, pk) -> x.pk = pk, PruneKind.values()) + .withArrayDimension("ELEM", (x, elem, idx) -> x.elements[idx] = elem, 5, ElementKind.values()) + .withDimension("QUAL", (x, qk) -> x.qk = qk, QualifierKind.values()) + .withDimension("EXPR", (x, ek) -> x.ek = ek, ExprKind.values()) + .run(TestDefaultSuperCall::new); } InterfaceKind ik; PruneKind pk; - Shape sh; + ElementKind[] elements = new ElementKind[5]; QualifierKind qk; ExprKind ek; - JavaSource source; - DiagnosticChecker diagChecker; + + boolean filterBadTopElement() { + return elements[0].isAllowedTop(); + } - TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh, - QualifierKind qk, ExprKind ek) { - this.ik = ik; - this.pk = pk; - this.sh = sh; - this.qk = qk; - this.ek = ek; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + boolean filterBadIntermediateElement() { + for (int i = 1 ; i < 4 ; i++) { + if (!elements[i].isAllowedEnclosing(elements[i - 1], i == 1)) { + return false; + } + } + return true; + } + + boolean filterBadTerminalElement() { + return elements[4].isAllowedEnclosing(elements[3], false) && !elements[4].isClassDecl(); } - class JavaSource extends SimpleJavaFileObject { - - String template = "interface E {}\n" + - "interface B { }\n" + - "#I\n" + - "#P\n" + - "#C"; - - String source; + String template = "interface E {}\n" + + "interface B { }\n" + + "#{INTF1}\n" + + "#{INTF2}\n" + + "#{ELEM[0].0}"; - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#I", ik.interfaceStr) - .replaceAll("#P", pk.interfaceStr) - .replaceAll("#C", sh.getShape(qk, ek)); - } + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(template, this::methodName) + .analyze()); + } - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + ComboParameter methodName(String parameterName) { + switch (parameterName) { + case "METH": + String methodName = ek == ExprKind.THIS ? "test" : "m"; + return new ComboParameter.Constant(methodName); + default: + return null; } } - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - processException(ex); - return; - } - check(); - } + void check(Result res) { + Shape sh = new Shape(elements); - void check() { boolean errorExpected = false; boolean badEnclosing = false; @@ -364,7 +343,7 @@ boolean found = false; for (int i = 0; i < sh.enclosingElements.size(); i++) { if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue; - if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) { + if (sh.enclosingNames.get(i).equals(qk.qualifierStr)) { found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i)); break; } @@ -388,10 +367,9 @@ } } - checkCount.incrementAndGet(); - if (diagChecker.errorFound != errorExpected) { - throw new AssertionError("Problem when compiling source:\n" + - source.getCharContent(true) + + if (res.hasErrors() != errorExpected) { + fail("Problem when compiling source:\n" + + res.compilationInfo() + "\nenclosingElems: " + sh.enclosingElements + "\nenclosingNames: " + sh.enclosingNames + "\nelementsWithMethod: " + sh.elementsWithMethod + @@ -399,20 +377,7 @@ "\nbad this: " + badThis + "\nbad super: " + badSuper + "\nqual kind: " + qk + - "\nfound error: " + diagChecker.errorFound); + "\nfound error: " + res.hasErrors()); } } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/failover/CheckAttributedTree.java --- a/langtools/test/tools/javac/failover/CheckAttributedTree.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 6970584 8006694 8062373 + * @bug 6970584 8006694 8062373 8129962 * @summary assorted position errors in compiler syntax trees * temporarily workaround combo tests are causing time out in several platforms * @library ../lib @@ -31,13 +31,10 @@ * jdk.compiler/com.sun.tools.javac.code * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm CheckAttributedTree -q -r -et ERRONEOUS . + * @build combo.ComboTestHelper + * @run main CheckAttributedTree -q -r -et ERRONEOUS . */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -56,6 +53,11 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Field; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -79,18 +81,14 @@ import javax.swing.text.BadLocationException; import javax.swing.text.DefaultHighlighter; import javax.swing.text.Highlighter; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.JavacTask; import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; import com.sun.source.util.TaskListener; -import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -101,6 +99,10 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*; +import combo.ComboTestHelper; +import combo.ComboInstance; +import combo.ComboTestHelper.IgnoreMode; + /** * Utility and test program to check validity of tree positions for tree nodes. * The program can be run standalone, or as a jtreg test. In standalone mode, @@ -113,7 +115,7 @@ * covering any new language features that may be tested in this test suite. */ -public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { +public class CheckAttributedTree { /** * Main entry point. * If test.src is set, program runs in jtreg mode, and will throw an Error @@ -125,7 +127,6 @@ public static void main(String... args) throws Exception { String testSrc = System.getProperty("test.src"); File baseDir = (testSrc == null) ? null : new File(testSrc); - throwAssertionOnError = false; boolean ok = new CheckAttributedTree().run(baseDir, args); if (!ok) { if (testSrc != null) // jtreg mode @@ -160,7 +161,6 @@ quiet = true; else if (arg.equals("-v")) { verbose = true; - printAll = true; } else if (arg.equals("-t") && i + 1 < args.length) tags.add(args[++i]); @@ -187,18 +187,37 @@ } } - for (File file: files) { - if (file.exists()) - test(file); - else - error("File not found: " + file); - } + ComboTestHelper cth = new ComboTestHelper<>(); + cth.withIgnoreMode(IgnoreMode.IGNORE_ALL) + .withFilter(FileChecker::checkFile) + .withDimension("FILE", (x, file) -> x.file = file, getAllFiles(files)) + .run(FileChecker::new); if (fileCount.get() != 1) errWriter.println(fileCount + " files read"); - checkAfterExec(false); + + if (verbose) { + System.out.println(errSWriter.toString()); + } + + return (gui || !cth.info().hasFailures()); + } - return (gui || errCount.get() == 0); + File[] getAllFiles(List roots) throws IOException { + long now = System.currentTimeMillis(); + ArrayList buf = new ArrayList<>(); + for (File file : roots) { + Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + buf.add(file.toFile()); + return FileVisitResult.CONTINUE; + } + }); + } + long delta = System.currentTimeMillis() - now; + System.err.println("All files = " + buf.size() + " " + delta); + return buf.toArray(new File[buf.size()]); } /** @@ -224,116 +243,217 @@ out.println(""); } - /** - * Test a file. If the file is a directory, it will be recursively scanned - * for java files. - * @param file the file or directory to test - */ - void test(final File file) { - if (excludeFiles.contains(file)) { - if (!quiet) - error("File " + file + " excluded"); - return; + class FileChecker extends ComboInstance { + + File file; + + boolean checkFile() { + if (!file.exists()) { + error("File not found: " + file); + return false; + } + if (excludeFiles.contains(file)) { + if (!quiet) + error("File " + file + " excluded"); + return false; + } + if (!file.getName().endsWith(".java")) { + if (!quiet) + error("File " + file + " ignored"); + return false; + } + + return true; } - if (file.isDirectory()) { - for (File f: file.listFiles()) { - test(f); + public void doWork() { + if (!file.exists()) { + error("File not found: " + file); + } + if (excludeFiles.contains(file)) { + if (!quiet) + error("File " + file + " excluded"); + return; + } + if (!file.getName().endsWith(".java")) { + if (!quiet) + error("File " + file + " ignored"); + } + try { + if (verbose) + errWriter.println(file); + fileCount.incrementAndGet(); + NPETester p = new NPETester(); + p.test(read(file)); + } catch (AttributionException e) { + if (!quiet) { + error("Error attributing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); } - return; + } + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws AttributionException if any errors occur while analyzing the file + */ + List> read(File file) throws IOException, AttributionException { + try { + Iterable files = fileManager().getJavaFileObjects(file); + final List analyzedElems = new ArrayList<>(); + final List trees = new ArrayList<>(); + Iterable elems = newCompilationTask() + .withWriter(pw) + .withOption("-XDshouldStopPolicy=ATTR") + .withOption("-XDverboseCompilePolicy") + .withSource(files.iterator().next()) + .withListener(new TaskListener() { + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) + analyzedElems.add(e.getTypeElement()); + } + + public void finished(TaskEvent e) { + if (e.getKind() == Kind.PARSE) + trees.add(e.getCompilationUnit()); + } + }).analyze().get(); + if (!elems.iterator().hasNext()) + throw new AttributionException("No results from analyze"); + List> res = new ArrayList<>(); + for (CompilationUnitTree t : trees) { + JCCompilationUnit cu = (JCCompilationUnit)t; + for (JCTree def : cu.defs) { + if (def.hasTag(CLASSDEF) && + analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) { + res.add(new Pair<>(cu, def)); + } + } + } + return res; + } + catch (Throwable t) { + throw new AttributionException("Exception while attributing file: " + file); + } } - if (file.isFile() && file.getName().endsWith(".java")) { - pool.execute(new Runnable() { - @Override - public void run() { + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(); + System.err.println(msg); + System.err.println(); + fail(msg); + } + + /** + * Main class for testing assertions concerning types/symbol + * left uninitialized after attribution + */ + private class NPETester extends TreeScanner { + void test(List> trees) { + for (Pair p : trees) { + sourcefile = p.fst.sourcefile; + endPosTable = p.fst.endPositions; + encl = new Info(p.snd, endPosTable); + p.snd.accept(this); + } + } + + @Override + public void scan(JCTree tree) { + if (tree == null || + excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) { + return; + } + + Info self = new Info(tree, endPosTable); + if (mandatoryType(tree)) { + check(tree.type != null, + "'null' field 'type' found in tree ", self); + if (tree.type==null) + Thread.dumpStack(); + } + + Field errField = checkFields(tree); + if (errField!=null) { + check(false, + "'null' field '" + errField.getName() + "' found in tree ", self); + } + + Info prevEncl = encl; + encl = self; + tree.accept(this); + encl = prevEncl; + } + + private boolean mandatoryType(JCTree that) { + return that instanceof JCTree.JCExpression || + that.hasTag(VARDEF) || + that.hasTag(METHODDEF) || + that.hasTag(CLASSDEF); + } + + private final List excludedFields = Arrays.asList("varargsElement", "targetType"); + + void check(boolean ok, String label, Info self) { + if (!ok) { + if (gui) { + if (viewer == null) + viewer = new Viewer(); + viewer.addEntry(sourcefile, label, encl, self); + } + error(label + self.toString() + " encl: " + encl.toString() + + " in file: " + sourcefile + " " + self.tree); + } + } + + Field checkFields(JCTree t) { + List fieldsToCheck = treeUtil.getFieldsOfType(t, + excludedFields, + Symbol.class, + Type.class); + for (Field f : fieldsToCheck) { try { - if (verbose) - errWriter.println(file); - fileCount.incrementAndGet(); - NPETester p = new NPETester(); - p.test(read(file)); - } catch (AttributionException e) { - if (!quiet) { - error("Error attributing " + file + "\n" + e.getMessage()); + if (f.get(t) == null) { + return f; } - } catch (IOException e) { - error("Error reading " + file + ": " + e); + } + catch (IllegalAccessException e) { + System.err.println("Cannot read field: " + f); + //swallow it } } - }); - return; + return null; + } + + @Override + public void visitImport(JCImport tree) { } + + @Override + public void visitTopLevel(JCCompilationUnit tree) { + scan(tree.defs); + } + + JavaFileObject sourcefile; + EndPosTable endPosTable; + Info encl; } - - if (!quiet) - error("File " + file + " ignored"); } // See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); - /** - * Read a file. - * @param file the file to be read - * @return the tree for the content of the file - * @throws IOException if any IO errors occur - * @throws AttributionException if any errors occur while analyzing the file - */ - List> read(File file) throws IOException, AttributionException { - r.errors = 0; - Iterable files = fm.get().getJavaFileObjects(file); - String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" }; - JavacTask task = (JavacTask)comp.getTask(pw, fm.get(), r, Arrays.asList(opts), null, files); - final List analyzedElems = new ArrayList<>(); - task.setTaskListener(new TaskListener() { - public void started(TaskEvent e) { - if (e.getKind() == TaskEvent.Kind.ANALYZE) - analyzedElems.add(e.getTypeElement()); - } - public void finished(TaskEvent e) { } - }); - int i = 0; - try { - Iterable trees = task.parse(); -// JavaCompiler c = JavaCompiler.instance(((JavacTaskImpl) task).getContext()); -// System.err.println("verboseCompilePolicy: " + c.verboseCompilePolicy); -// System.err.println("shouldStopIfError: " + c.shouldStopPolicyIfError); -// System.err.println("shouldStopIfNoError: " + c.shouldStopPolicyIfNoError); - Iterable elems = task.analyze(); - if (!elems.iterator().hasNext()) - throw new AttributionException("No results from analyze"); - List> res = new ArrayList<>(); - //System.err.println("Try to add pairs. Elems are " + analyzedElems); - for (CompilationUnitTree t : trees) { - JCCompilationUnit cu = (JCCompilationUnit)t; - for (JCTree def : cu.defs) { - if (def.hasTag(CLASSDEF) && - analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) { - //System.err.println("Adding pair..." + cu.sourcefile + " " + ((JCTree.JCClassDecl) def).name); - res.add((i++ % 2) == 0 ? new Pair<>(cu, def) {} : new Pair<>(cu, def)); - } - } - } - return res; - } - catch (Throwable t) { - throw new AttributionException("Exception while attributing file: " + file); - } - } - - /** - * Report an error. When the program is complete, the program will either - * exit or throw an Error if any errors have been reported. - * @param msg the error message - */ - void error(String msg) { - System.err.println(); - System.err.println(msg); - System.err.println(); - errCount.incrementAndGet(); - } + StringWriter errSWriter = new StringWriter(); + PrintWriter errWriter = new PrintWriter(errSWriter); /** Flag: don't report irrelevant files. */ boolean quiet; @@ -356,101 +476,6 @@ TreeUtil treeUtil = new TreeUtil(); /** - * Main class for testing assertions concerning types/symbol - * left uninitialized after attribution - */ - private class NPETester extends TreeScanner { - void test(List> trees) { - for (Pair p : trees) { -// System.err.println("checking " + p.fst.sourcefile); - sourcefile = p.fst.sourcefile; - endPosTable = p.fst.endPositions; - encl = new Info(p.snd, endPosTable); - p.snd.accept(this); - } - } - - @Override - public void scan(JCTree tree) { - if (tree == null || - excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) { - return; - } - - Info self = new Info(tree, endPosTable); - if (mandatoryType(tree)) { - check(tree.type != null, - "'null' field 'type' found in tree ", self); - if (tree.type==null) - Thread.dumpStack(); - } - - Field errField = checkFields(tree); - if (errField!=null) { - check(false, - "'null' field '" + errField.getName() + "' found in tree ", self); - } - - Info prevEncl = encl; - encl = self; - tree.accept(this); - encl = prevEncl; - } - - private boolean mandatoryType(JCTree that) { - return that instanceof JCTree.JCExpression || - that.hasTag(VARDEF) || - that.hasTag(METHODDEF) || - that.hasTag(CLASSDEF); - } - - private final List excludedFields = Arrays.asList("varargsElement", "targetType"); - - void check(boolean ok, String label, Info self) { - if (!ok) { - if (gui) { - if (viewer == null) - viewer = new Viewer(); - viewer.addEntry(sourcefile, label, encl, self); - } - error(label + self.toString() + " encl: " + encl.toString() + - " in file: " + sourcefile + " " + self.tree); - } - } - - Field checkFields(JCTree t) { - List fieldsToCheck = treeUtil.getFieldsOfType(t, - excludedFields, - Symbol.class, - Type.class); - for (Field f : fieldsToCheck) { - try { - if (f.get(t) == null) { - return f; - } - } - catch (IllegalAccessException e) { - System.err.println("Cannot read field: " + f); - //swallow it - } - } - return null; - } - - @Override - public void visitImport(JCImport tree) { } - - @Override - public void visitTopLevel(JCCompilationUnit tree) { - scan(tree.defs); - } - - JavaFileObject sourcefile; - EndPosTable endPosTable; - Info encl; - } - - /** * Utility class providing easy access to position and other info for a tree node. */ private class Info { @@ -524,25 +549,6 @@ } /** - * DiagnosticListener to report diagnostics and count any errors that occur. - */ - private static class Reporter implements DiagnosticListener { - Reporter(PrintWriter out) { - this.out = out; - } - - public void report(Diagnostic diagnostic) { - //out.println(diagnostic); - switch (diagnostic.getKind()) { - case ERROR: - errors++; - } - } - int errors; - PrintWriter out; - } - - /** * GUI viewer for issues found by TreePosTester. The viewer provides a drop * down list for selecting error conditions, a header area providing details * about an error, and a text area with the ranges of text highlighted as diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java --- a/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,30 +23,32 @@ /* * @test - * @bug 7046778 8006694 + * @bug 7046778 8006694 8129962 * @summary Project Coin: problem with diamond and member inner classes * temporarily workaround combo tests are causing time out in several platforms - * @library ../../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm DiamondAndInnerClassTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @compile -Xlint:all DiamondAndInnerClassTest.java + * @run main DiamondAndInnerClassTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import com.sun.source.util.JavacTask; -import java.net.URI; +import java.io.IOException; import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -public class DiamondAndInnerClassTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +import combo.ComboTestHelper; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; - enum TypeArgumentKind { +public class DiamondAndInnerClassTest extends ComboInstance { + + enum TypeArgumentKind implements ComboParameter { NONE(""), STRING(""), INTEGER(""), @@ -54,7 +56,7 @@ String typeargStr; - private TypeArgumentKind(String typeargStr) { + TypeArgumentKind(String typeargStr) { this.typeargStr = typeargStr; } @@ -75,252 +77,173 @@ default: throw new AssertionError("Unexpected decl kind: " + this); } } + + @Override + public String expand(String optParameter) { + return typeargStr; + } } - enum ArgumentKind { + enum ArgumentKind implements ComboParameter { OBJECT("(Object)null"), STRING("(String)null"), INTEGER("(Integer)null"); String argStr; - private ArgumentKind(String argStr) { + ArgumentKind(String argStr) { this.argStr = argStr; } + + @Override + public String expand(String optParameter) { + return argStr; + } } - enum TypeQualifierArity { - ONE(1, "A1#TA1"), - TWO(2, "A1#TA1.A2#TA2"), - THREE(3, "A1#TA1.A2#TA2.A3#TA3"); + enum TypeQualifierArity implements ComboParameter { + ONE(1, "A1#{TA#IDX[0]}"), + TWO(2, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}"), + THREE(3, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}.A3#{TA#IDX[2]}"); int n; String qualifierStr; - private TypeQualifierArity(int n, String qualifierStr) { + TypeQualifierArity(int n, String qualifierStr) { this.n = n; this.qualifierStr = qualifierStr; } - String getType(TypeArgumentKind... typeArgumentKinds) { - String res = qualifierStr; - for (int i = 1 ; i <= typeArgumentKinds.length ; i++) { - res = res.replace("#TA" + i, typeArgumentKinds[i-1].typeargStr); - } - return res; - } - - boolean matches(InnerClassDeclArity innerClassDeclArity) { - return n ==innerClassDeclArity.n; + @Override + public String expand(String optParameter) { + return qualifierStr.replaceAll("#IDX", optParameter); } } - enum InnerClassDeclArity { - ONE(1, "class A1 { A1(X x1) { } #B }"), - TWO(2, "class A1 { class A2 { A2(X1 x1, X2 x2) { } #B } }"), - THREE(3, "class A1 { class A2 { class A3 { A3(X1 x1, X2 x2, X3 x3) { } #B } } }"); + enum InnerClassDeclArity implements ComboParameter { + ONE(1, "class A1 { A1(X x1) { } #{BODY} }"), + TWO(2, "class A1 { class A2 { A2(X1 x1, X2 x2) { } #{BODY} } }"), + THREE(3, "class A1 { class A2 { class A3 { A3(X1 x1, X2 x2, X3 x3) { } #{BODY} } } }"); int n; String classDeclStr; - private InnerClassDeclArity(int n, String classDeclStr) { + InnerClassDeclArity(int n, String classDeclStr) { this.n = n; this.classDeclStr = classDeclStr; } + + @Override + public String expand(String optParameter) { + return classDeclStr; + } } - enum ArgumentListArity { - ONE(1, "(#A1)"), - TWO(2, "(#A1,#A2)"), - THREE(3, "(#A1,#A2,#A3)"); + enum ArgumentListArity implements ComboParameter { + ONE(1, "(#{A[0]})"), + TWO(2, "(#{A[0]},#{A[1]})"), + THREE(3, "(#{A[0]},#{A[1]},#{A[2]})"); int n; String argListStr; - private ArgumentListArity(int n, String argListStr) { + ArgumentListArity(int n, String argListStr) { this.n = n; this.argListStr = argListStr; } - String getArgs(ArgumentKind... argumentKinds) { - String res = argListStr; - for (int i = 1 ; i <= argumentKinds.length ; i++) { - res = res.replace("#A" + i, argumentKinds[i-1].argStr); - } - return res; - } - - boolean matches(InnerClassDeclArity innerClassDeclArity) { - return n ==innerClassDeclArity.n; + @Override + public String expand(String optParameter) { + return argListStr.replaceAll("#IDX", optParameter); } } public static void main(String... args) throws Exception { - for (InnerClassDeclArity innerClassDeclArity : InnerClassDeclArity.values()) { - for (TypeQualifierArity declType : TypeQualifierArity.values()) { - if (!declType.matches(innerClassDeclArity)) continue; - for (TypeQualifierArity newClassType : TypeQualifierArity.values()) { - if (!newClassType.matches(innerClassDeclArity)) continue; - for (ArgumentListArity argList : ArgumentListArity.values()) { - if (!argList.matches(innerClassDeclArity)) continue; - for (TypeArgumentKind taDecl1 : TypeArgumentKind.values()) { - boolean isDeclRaw = taDecl1 == TypeArgumentKind.NONE; - //no diamond on decl site - if (taDecl1 == TypeArgumentKind.DIAMOND) continue; - for (TypeArgumentKind taSite1 : TypeArgumentKind.values()) { - boolean isSiteRaw = - taSite1 == TypeArgumentKind.NONE; - //diamond only allowed on the last type qualifier - if (taSite1 == TypeArgumentKind.DIAMOND && - innerClassDeclArity != - InnerClassDeclArity.ONE) - continue; - for (ArgumentKind arg1 : ArgumentKind.values()) { - if (innerClassDeclArity == innerClassDeclArity.ONE) { - pool.execute( - new DiamondAndInnerClassTest( - innerClassDeclArity, declType, - newClassType, argList, - new TypeArgumentKind[] {taDecl1}, - new TypeArgumentKind[] {taSite1}, - new ArgumentKind[] {arg1})); - continue; - } - for (TypeArgumentKind taDecl2 : TypeArgumentKind.values()) { - //no rare types - if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE)) - continue; - //no diamond on decl site - if (taDecl2 == TypeArgumentKind.DIAMOND) - continue; - for (TypeArgumentKind taSite2 : TypeArgumentKind.values()) { - //no rare types - if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE)) - continue; - //diamond only allowed on the last type qualifier - if (taSite2 == TypeArgumentKind.DIAMOND && - innerClassDeclArity != InnerClassDeclArity.TWO) - continue; - for (ArgumentKind arg2 : ArgumentKind.values()) { - if (innerClassDeclArity == innerClassDeclArity.TWO) { - pool.execute( - new DiamondAndInnerClassTest( - innerClassDeclArity, - declType, - newClassType, - argList, - new TypeArgumentKind[] {taDecl1, taDecl2}, - new TypeArgumentKind[] {taSite1, taSite2}, - new ArgumentKind[] {arg1, arg2})); - continue; - } - for (TypeArgumentKind taDecl3 : TypeArgumentKind.values()) { - //no rare types - if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE)) - continue; - //no diamond on decl site - if (taDecl3 == TypeArgumentKind.DIAMOND) - continue; - for (TypeArgumentKind taSite3 : TypeArgumentKind.values()) { - //no rare types - if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE)) - continue; - //diamond only allowed on the last type qualifier - if (taSite3 == TypeArgumentKind.DIAMOND && - innerClassDeclArity != InnerClassDeclArity.THREE) - continue; - for (ArgumentKind arg3 : ArgumentKind.values()) { - if (innerClassDeclArity == - innerClassDeclArity.THREE) { - pool.execute( - new DiamondAndInnerClassTest( - innerClassDeclArity, - declType, - newClassType, - argList, - new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3}, - new TypeArgumentKind[] {taSite1, taSite2, taSite3}, - new ArgumentKind[] {arg1, arg2, arg3})); - continue; - } - } - } - } - } - } - } - } - } - } - } + new ComboTestHelper() + .withFilter(DiamondAndInnerClassTest::rareTypesFilter) + .withFilter(DiamondAndInnerClassTest::noDiamondOnDecl) + .withFilter(DiamondAndInnerClassTest::noDiamondOnIntermediateTypes) + .withFilter(DiamondAndInnerClassTest::arityMismatch) + .withFilter(DiamondAndInnerClassTest::redundantFilter) + .withDimension("BODY", new ComboParameter.Constant<>("#{D.1} res = new #{S.2}#{AL};")) + .withDimension("DECL", (x, arity) -> x.innerClassDeclArity = arity, InnerClassDeclArity.values()) + .withDimension("D", (x, arity) -> x.declArity = arity, TypeQualifierArity.values()) + .withDimension("S", (x, arity) -> x.siteArity = arity, TypeQualifierArity.values()) + .withDimension("AL", (x, alist) -> x.argumentListArity = alist, ArgumentListArity.values()) + .withArrayDimension("TA1", (x, targs, idx) -> x.declTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) + .withArrayDimension("TA2", (x, targs, idx) -> x.siteTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) + .withArrayDimension("A", (x, argsk, idx) -> x.argumentKinds[idx] = argsk, 3, ArgumentKind.values()) + .run(DiamondAndInnerClassTest::new); + } + + InnerClassDeclArity innerClassDeclArity; + TypeQualifierArity declArity; + TypeQualifierArity siteArity; + TypeArgumentKind[] declTypeArgumentKinds = new TypeArgumentKind[3]; + TypeArgumentKind[] siteTypeArgumentKinds = new TypeArgumentKind[3]; + ArgumentKind[] argumentKinds = new ArgumentKind[3]; + ArgumentListArity argumentListArity; + + boolean rareTypesFilter() { + for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { + boolean isRaw = types[0] == TypeArgumentKind.NONE; + for (int i = 1; i < innerClassDeclArity.n; i++) { + if (isRaw != (types[i] == TypeArgumentKind.NONE)) { + return false; } } } + return true; + } - checkAfterExec(); + boolean noDiamondOnDecl() { + for (int i = 0; i < innerClassDeclArity.n; i++) { + if (declTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { + return false; + } + } + return true; + } + + boolean noDiamondOnIntermediateTypes() { + for (int i = 0; i < (innerClassDeclArity.n - 1); i++) { + if (siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { + return false; + } + } + return true; } - InnerClassDeclArity innerClassDeclArity; - TypeQualifierArity declType; - TypeQualifierArity siteType; - ArgumentListArity argList; - TypeArgumentKind[] declTypeArgumentKinds; - TypeArgumentKind[] siteTypeArgumentKinds; - ArgumentKind[] argumentKinds; - JavaSource source; - DiagnosticChecker diagChecker; - - DiamondAndInnerClassTest(InnerClassDeclArity innerClassDeclArity, - TypeQualifierArity declType, TypeQualifierArity siteType, - ArgumentListArity argList, TypeArgumentKind[] declTypeArgumentKinds, - TypeArgumentKind[] siteTypeArgumentKinds, ArgumentKind[] argumentKinds) { - this.innerClassDeclArity = innerClassDeclArity; - this.declType = declType; - this.siteType = siteType; - this.argList = argList; - this.declTypeArgumentKinds = declTypeArgumentKinds; - this.siteTypeArgumentKinds = siteTypeArgumentKinds; - this.argumentKinds = argumentKinds; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + boolean redundantFilter() { + for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { + for (int i = innerClassDeclArity.n; i < types.length; i++) { + if (types[i].ordinal() != 0) { + return false; + } + } + } + for (int i = innerClassDeclArity.n; i < argumentKinds.length; i++) { + if (argumentKinds[i].ordinal() != 0) { + return false; + } + } + return true; } - class JavaSource extends SimpleJavaFileObject { - - String bodyTemplate = "#D res = new #S#AL;"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = innerClassDeclArity.classDeclStr.replace("#B", bodyTemplate) - .replace("#D", declType.getType(declTypeArgumentKinds)) - .replace("#S", siteType.getType(siteTypeArgumentKinds)) - .replace("#AL", argList.getArgs(argumentKinds)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } + boolean arityMismatch() { + return argumentListArity.n == innerClassDeclArity.n && + siteArity.n == innerClassDeclArity.n && + declArity.n == innerClassDeclArity.n; } @Override - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - throw new AssertionError("Error thrown when compiling the following code:\n" + - source.getCharContent(true)); - } - check(); + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate("#{DECL}") + .analyze()); } - void check() { - checkCount.incrementAndGet(); - + void check(Result res) { boolean errorExpected = false; TypeArgumentKind[] expectedArgKinds = @@ -345,24 +268,11 @@ } } - if (errorExpected != diagChecker.errorFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound error: " + diagChecker.errorFound + + if (errorExpected != res.hasErrors()) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound error: " + res.hasErrors() + "\nExpected error: " + errorExpected); } } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java --- a/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,29 +23,29 @@ /* * @test - * @bug 7062745 8006694 + * @bug 7062745 8006694 8129962 * @summary Regression: difference in overload resolution when two methods * are maximally specific * temporarily workaround combo tests are causing time out in several platforms - * @library ../../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm GenericOverrideTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main GenericOverrideTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -public class GenericOverrideTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class GenericOverrideTest extends ComboInstance { enum SourceLevel { SOURCE_7("-source", "7"), @@ -58,24 +58,29 @@ } } - enum SignatureKind { + enum SignatureKind implements ComboParameter { NON_GENERIC(""), GENERIC(""); String paramStr; - private SignatureKind(String paramStr) { + SignatureKind(String paramStr) { this.paramStr = paramStr; } + + @Override + public String expand(String optParameter) { + return paramStr; + } } - enum ReturnTypeKind { + enum ReturnTypeKind implements ComboParameter { LIST("List"), ARRAYLIST("ArrayList"); String retStr; - private ReturnTypeKind(String retStr) { + ReturnTypeKind(String retStr) { this.retStr = retStr; } @@ -88,9 +93,14 @@ default: throw new AssertionError("Unexpected ret kind: " + this); } } + + @Override + public String expand(String optParameter) { + return retStr; + } } - enum TypeArgumentKind { + enum TypeArgumentKind implements ComboParameter { NONE(""), UNBOUND(""), INTEGER(""), @@ -99,7 +109,7 @@ String typeargStr; - private TypeArgumentKind(String typeargStr) { + TypeArgumentKind(String typeargStr) { this.typeargStr = typeargStr; } @@ -141,136 +151,79 @@ default: throw new AssertionError("Unexpected typearg kind: " + this); } } + + @Override + public String expand(String optParameter) { + return typeargStr; + } } public static void main(String... args) throws Exception { - for (SignatureKind sig1 : SignatureKind.values()) { - for (ReturnTypeKind rt1 : ReturnTypeKind.values()) { - for (TypeArgumentKind ta1 : TypeArgumentKind.values()) { - if (!ta1.compatibleWith(sig1)) continue; - for (SignatureKind sig2 : SignatureKind.values()) { - for (ReturnTypeKind rt2 : ReturnTypeKind.values()) { - for (TypeArgumentKind ta2 : TypeArgumentKind.values()) { - if (!ta2.compatibleWith(sig2)) continue; - for (ReturnTypeKind rt3 : ReturnTypeKind.values()) { - for (TypeArgumentKind ta3 : TypeArgumentKind.values()) { - if (!ta3.compatibleWith(SignatureKind.NON_GENERIC)) - continue; - for (SourceLevel level : SourceLevel.values()) { - pool.execute( - new GenericOverrideTest(sig1, - rt1, ta1, sig2, rt2, - ta2, rt3, ta3, level)); - } - } - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withFilter(GenericOverrideTest::argMismatchFilter) + .withDimension("SOURCE", (x, level) -> x.level = level, SourceLevel.values()) + .withArrayDimension("SIG", (x, sig, idx) -> x.sigs[idx] = sig, 2, SignatureKind.values()) + .withArrayDimension("TARG", (x, targ, idx) -> x.targs[idx] = targ, 3, TypeArgumentKind.values()) + .withArrayDimension("RET", (x, ret, idx) -> x.rets[idx] = ret, 3, ReturnTypeKind.values()) + .run(GenericOverrideTest::new); } - SignatureKind sig1, sig2; - ReturnTypeKind rt1, rt2, rt3; - TypeArgumentKind ta1, ta2, ta3; + SignatureKind[] sigs = new SignatureKind[2]; + ReturnTypeKind[] rets = new ReturnTypeKind[3]; + TypeArgumentKind[] targs = new TypeArgumentKind[3]; SourceLevel level; - JavaSource source; - DiagnosticChecker diagChecker; - GenericOverrideTest(SignatureKind sig1, ReturnTypeKind rt1, TypeArgumentKind ta1, - SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2, - ReturnTypeKind rt3, TypeArgumentKind ta3, SourceLevel level) { - this.sig1 = sig1; - this.sig2 = sig2; - this.rt1 = rt1; - this.rt2 = rt2; - this.rt3 = rt3; - this.ta1 = ta1; - this.ta2 = ta2; - this.ta3 = ta3; - this.level = level; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + boolean argMismatchFilter() { + return targs[0].compatibleWith(sigs[0]) && + targs[1].compatibleWith(sigs[1]) && + targs[2].compatibleWith(SignatureKind.NON_GENERIC); } - class JavaSource extends SimpleJavaFileObject { - - String template = "import java.util.*;\n" + - "interface A { #S1 #R1#TA1 m(); }\n" + - "interface B { #S2 #R2#TA2 m(); }\n" + - "interface AB extends A, B {}\n" + - "class Test {\n" + - " void test(AB ab) { #R3#TA3 n = ab.m(); }\n" + - "}"; - - String source; + String template = "import java.util.*;\n" + + "interface A { #{SIG[0]} #{RET[0]}#{TARG[0]} m(); }\n" + + "interface B { #{SIG[1]} #{RET[1]}#{TARG[1]} m(); }\n" + + "interface AB extends A, B {}\n" + + "class Test {\n" + + " void test(AB ab) { #{RET[2]}#{TARG[2]} n = ab.m(); }\n" + + "}"; - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replace("#S1", sig1.paramStr). - replace("#S2", sig2.paramStr). - replace("#R1", rt1.retStr). - replace("#R2", rt2.retStr). - replace("#R3", rt3.retStr). - replace("#TA1", ta1.typeargStr). - replace("#TA2", ta2.typeargStr). - replace("#TA3", ta3.typeargStr); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withOption("-XDuseUnsharedTable") //this test relies on predictable name indexes! + .withOptions(level.opts) + .withSourceFromTemplate(template) + .analyze()); } - @Override - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - level.opts != null ? Arrays.asList(level.opts) : null, - null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - throw new AssertionError("Error thrown when compiling the following code:\n" + - source.getCharContent(true)); - } - check(); - } - - void check() { - checkCount.incrementAndGet(); - + void check(Result res) { boolean errorExpected = false; int mostSpecific = 0; //first check that either |R1| <: |R2| or |R2| <: |R1| - if (rt1 != rt2) { - if (!rt1.moreSpecificThan(rt2) && - !rt2.moreSpecificThan(rt1)) { + if (rets[0] != rets[1]) { + if (!rets[0].moreSpecificThan(rets[1]) && + !rets[1].moreSpecificThan(rets[0])) { errorExpected = true; } else { - mostSpecific = rt1.moreSpecificThan(rt2) ? 1 : 2; + mostSpecific = rets[0].moreSpecificThan(rets[1]) ? 1 : 2; } } //check that either TA1 <= TA2 or TA2 <= TA1 (unless most specific return found above is raw) if (!errorExpected) { - if (ta1 != ta2) { - boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) || - ta2.moreSpecificThan(ta1, true); - if (!ta1.moreSpecificThan(ta2, useStrictCheck) && - !ta2.moreSpecificThan(ta1, useStrictCheck)) { + if (targs[0] != targs[1]) { + boolean useStrictCheck = targs[0].moreSpecificThan(targs[1], true) || + targs[1].moreSpecificThan(targs[0], true); + if (!targs[0].moreSpecificThan(targs[1], useStrictCheck) && + !targs[1].moreSpecificThan(targs[0], useStrictCheck)) { errorExpected = true; } else { - int mostSpecific2 = ta1.moreSpecificThan(ta2, useStrictCheck) ? 1 : 2; + int mostSpecific2 = targs[0].moreSpecificThan(targs[1], useStrictCheck) ? 1 : 2; if (mostSpecific != 0 && mostSpecific2 != mostSpecific) { errorExpected = mostSpecific == 1 ? - ta1 != TypeArgumentKind.NONE : - ta2 != TypeArgumentKind.NONE; + targs[0] != TypeArgumentKind.NONE : + targs[1] != TypeArgumentKind.NONE; } else { mostSpecific = mostSpecific2; } @@ -284,34 +237,21 @@ //finally, check that most specific return type is compatible with expected type if (!errorExpected) { - ReturnTypeKind msrt = mostSpecific == 1 ? rt1 : rt2; - TypeArgumentKind msta = mostSpecific == 1 ? ta1 : ta2; - SignatureKind mssig = mostSpecific == 1 ? sig1 : sig2; + ReturnTypeKind msrt = mostSpecific == 1 ? rets[0] : rets[1]; + TypeArgumentKind msta = mostSpecific == 1 ? targs[0] : targs[1]; + SignatureKind mssig = mostSpecific == 1 ? sigs[0] : sigs[1]; - if (!msrt.moreSpecificThan(rt3) || - !msta.assignableTo(ta3, mssig, level)) { + if (!msrt.moreSpecificThan(rets[2]) || + !msta.assignableTo(targs[2], mssig, level)) { errorExpected = true; } } - if (errorExpected != diagChecker.errorFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound error: " + diagChecker.errorFound + + if (errorExpected != res.hasErrors()) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound error: " + res.hasErrors() + "\nExpected error: " + errorExpected); } } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java --- a/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,35 +23,32 @@ /** * @test - * @bug 8003280 8004102 8006694 + * @bug 8003280 8004102 8006694 8129962 * @summary Add lambda tests * perform several automated checks in lambda conversion, esp. around accessibility * temporarily workaround combo tests are causing time out in several platforms - * @author Maurizio Cimadamore - * @library ../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/timeout=600/othervm FunctionalInterfaceConversionTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main FunctionalInterfaceConversionTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; -import com.sun.source.util.JavacTask; -public class FunctionalInterfaceConversionTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - enum PackageKind { + +public class FunctionalInterfaceConversionTest extends ComboInstance { + + enum PackageKind implements ComboParameter { NO_PKG(""), PKG_A("a"); @@ -61,7 +58,8 @@ this.pkg = pkg; } - String getPkgDecl() { + @Override + public String expand(String optParameter) { return this == NO_PKG ? "" : "package " + pkg + ";"; @@ -74,12 +72,12 @@ } } - enum SamKind { + enum SamKind implements ComboParameter { CLASS("public class Sam { }"), ABSTACT_CLASS("public abstract class Sam { }"), ANNOTATION("public @interface Sam { }"), ENUM("public enum Sam { }"), - INTERFACE("public interface Sam { \n #METH; \n }"); + INTERFACE("public interface Sam { \n #{METH1}; \n }"); String sam_str; @@ -87,12 +85,13 @@ this.sam_str = sam_str; } - String getSam(String methStr) { - return sam_str.replaceAll("#METH", methStr); + @Override + public String expand(String optParameter) { + return sam_str; } } - enum ModifierKind { + enum ModifierKind implements ComboParameter { PUBLIC("public"), PACKAGE(""); @@ -102,77 +101,73 @@ this.modifier_str = modifier_str; } - boolean stricterThan(ModifierKind that) { - return this.ordinal() > that.ordinal(); + @Override + public String expand(String optParameter) { + return modifier_str; } } - enum TypeKind { + enum TypeKind implements ComboParameter { EXCEPTION("Exception"), PKG_CLASS("PackageClass"); String typeStr; - private TypeKind(String typeStr) { + TypeKind(String typeStr) { this.typeStr = typeStr; } + + @Override + public String expand(String optParameter) { + return typeStr; + } } - enum ExprKind { + enum ExprKind implements ComboParameter { LAMBDA("x -> null"), MREF("this::m"); String exprStr; - private ExprKind(String exprStr) { + ExprKind(String exprStr) { this.exprStr = exprStr; } + + @Override + public String expand(String optParameter) { + return exprStr; + } } - enum MethodKind { + enum MethodKind implements ComboParameter { NONE(""), - NON_GENERIC("public abstract #R m(#ARG s) throws #T;"), - GENERIC("public abstract #R m(#ARG s) throws #T;"); + NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"), + GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"); String methodTemplate; - private MethodKind(String methodTemplate) { + MethodKind(String methodTemplate) { this.methodTemplate = methodTemplate; } - String getMethod(TypeKind retType, TypeKind argType, TypeKind thrownType) { - return methodTemplate.replaceAll("#R", retType.typeStr). - replaceAll("#ARG", argType.typeStr). - replaceAll("#T", thrownType.typeStr); + @Override + public String expand(String optParameter) { + return methodTemplate; } } public static void main(String[] args) throws Exception { - for (PackageKind samPkg : PackageKind.values()) { - for (ModifierKind modKind : ModifierKind.values()) { - for (SamKind samKind : SamKind.values()) { - for (MethodKind samMeth : MethodKind.values()) { - for (MethodKind clientMeth : MethodKind.values()) { - for (TypeKind retType : TypeKind.values()) { - for (TypeKind argType : TypeKind.values()) { - for (TypeKind thrownType : TypeKind.values()) { - for (ExprKind exprKind : ExprKind.values()) { - pool.execute( - new FunctionalInterfaceConversionTest( - samPkg, modKind, samKind, - samMeth, clientMeth, retType, - argType, thrownType, exprKind)); - } - } - } - } - } - } - } - } - } - - checkAfterExec(false); + new ComboTestHelper() + .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values()) + .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) + .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values()) + .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values()) + .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values()) + .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values()) + .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values()) + .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values()) + .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values()) + .run(FunctionalInterfaceConversionTest::new); } PackageKind samPkg; @@ -184,70 +179,32 @@ TypeKind argType; TypeKind thrownType; ExprKind exprKind; - DiagnosticChecker dc; - SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") { - @Override - public String toString() { - return template.replaceAll("#P", samPkg.getPkgDecl()). - replaceAll("#C", samKind.getSam( - samMeth.getMethod(retType, argType, thrownType))); - } - }; - - SourceFile pkgClassSourceFile = - new SourceFile("PackageClass.java", - "#P\n #M class PackageClass extends Exception { }") { - @Override - public String toString() { - return template.replaceAll("#P", samPkg.getPkgDecl()). - replaceAll("#M", modKind.modifier_str); - } - }; + String samSource = "#{PKG} \n #{CLAZZ}"; + String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }"; + String clientSource = "#{IMP}\n abstract class Client { \n" + + " Sam s = #{EXPR};\n" + + " #{METH2} \n }"; - SourceFile clientSourceFile = - new SourceFile("Client.java", - "#I\n abstract class Client { \n" + - " Sam s = #E;\n" + - " #M \n }") { - @Override - public String toString() { - return template.replaceAll("#I", samPkg.getImportStat()) - .replaceAll("#E", exprKind.exprStr) - .replaceAll("#M", clientMeth.getMethod(retType, argType, thrownType)); - } - }; - - FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind, - SamKind samKind, MethodKind samMeth, MethodKind clientMeth, - TypeKind retType, TypeKind argType, TypeKind thrownType, - ExprKind exprKind) { - this.samPkg = samPkg; - this.modKind = modKind; - this.samKind = samKind; - this.samMeth = samMeth; - this.clientMeth = clientMeth; - this.retType = retType; - this.argType = argType; - this.thrownType = thrownType; - this.exprKind = exprKind; - this.dc = new DiagnosticChecker(); + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate("Sam", samSource) + .withSourceFromTemplate("PackageClass", pkgClassSource) + .withSourceFromTemplate("Client", clientSource, this::importStmt) + .analyze()); } - @Override - public void run() { - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + ComboParameter importStmt(String name) { + switch (name) { + case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat()); + default: return null; + } + } - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null, - Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile)); - try { - ct.analyze(); - } catch (IOException ex) { - throw new AssertionError("Test failing with cause", ex.getCause()); - } - if (dc.errorFound == checkSamConversion()) { - throw new AssertionError(samSourceFile + "\n\n" + - pkgClassSourceFile + "\n\n" + clientSourceFile); + void check(Result res) { + if (res.hasErrors() == checkSamConversion()) { + fail("Unexpected compilation result; " + res.compilationInfo()); } } @@ -276,35 +233,4 @@ return true; } } - - abstract class SourceFile extends SimpleJavaFileObject { - - protected String template; - - public SourceFile(String filename, String template) { - super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); - this.template = template; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return toString(); - } - - @Override - public abstract String toString(); - } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound = false; - - @Override - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/LambdaParserTest.java --- a/langtools/test/tools/javac/lambda/LambdaParserTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,39 +23,40 @@ /* * @test - * @bug 7115050 8003280 8005852 8006694 + * @bug 7115050 8003280 8005852 8006694 8129962 * @summary Add lambda tests * Add parser support for lambda expressions * temporarily workaround combo tests are causing time out in several platforms - * @library ../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm LambdaParserTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + + * @run main LambdaParserTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -public class LambdaParserTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class LambdaParserTest extends ComboInstance { - enum LambdaKind { + enum LambdaKind implements ComboParameter { NILARY_EXPR("()->x"), NILARY_STMT("()->{ return x; }"), - ONEARY_SHORT_EXPR("#PN->x"), - ONEARY_SHORT_STMT("#PN->{ return x; }"), - ONEARY_EXPR("(#M1 #T1 #PN)->x"), - ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"), - TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"), - TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }"); + ONEARY_SHORT_EXPR("#{NAME}->x"), + ONEARY_SHORT_STMT("#{NAME}->{ return x; }"), + ONEARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME})->x"), + ONEARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME})->{ return x; }"), + TWOARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->x"), + TWOARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->{ return x; }"); String lambdaTemplate; @@ -63,13 +64,9 @@ this.lambdaTemplate = lambdaTemplate; } - String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) { - return lambdaTemplate.replaceAll("#M1", mk1.modifier) - .replaceAll("#M2", mk2.modifier) - .replaceAll("#T1", pk1.parameterType) - .replaceAll("#T2", pk2.parameterType) - .replaceAll("#PN", pn.nameStr); + @Override + public String expand(String optParameter) { + return lambdaTemplate; } int arity() { @@ -92,7 +89,7 @@ } } - enum LambdaParameterName { + enum LambdaParameterName implements ComboParameter { IDENT("x"), UNDERSCORE("_"); @@ -101,9 +98,14 @@ LambdaParameterName(String nameStr) { this.nameStr = nameStr; } + + @Override + public String expand(String optParameter) { + return nameStr; + } } - enum LambdaParameterKind { + enum LambdaParameterKind implements ComboParameter { IMPLICIT(""), EXPLIICT_SIMPLE("A"), EXPLIICT_SIMPLE_ARR1("A[]"), @@ -129,9 +131,14 @@ return this == EXPLICIT_VARARGS || this == EXPLICIT_GENERIC2_VARARGS; } + + @Override + public String expand(String optParameter) { + return parameterType; + } } - enum ModifierKind { + enum ModifierKind implements ComboParameter { NONE(""), FINAL("final"), PUBLIC("public"); @@ -150,15 +157,20 @@ default: throw new AssertionError("Invalid modifier kind " + this); } } + + @Override + public String expand(String optParameter) { + return modifier; + } } - enum ExprKind { - NONE("#L#S"), - SINGLE_PAREN1("(#L#S)"), - SINGLE_PAREN2("(#L)#S"), - DOUBLE_PAREN1("((#L#S))"), - DOUBLE_PAREN2("((#L)#S)"), - DOUBLE_PAREN3("((#L))#S"); + enum ExprKind implements ComboParameter { + NONE("#{LAMBDA}#{SUBEXPR}"), + SINGLE_PAREN1("(#{LAMBDA}#{SUBEXPR})"), + SINGLE_PAREN2("(#{LAMBDA})#{SUBEXPR}"), + DOUBLE_PAREN1("((#{LAMBDA}#{SUBEXPR}))"), + DOUBLE_PAREN2("((#{LAMBDA})#{SUBEXPR})"), + DOUBLE_PAREN3("((#{LAMBDA}))#{SUBEXPR}"); String expressionTemplate; @@ -166,14 +178,13 @@ this.expressionTemplate = expressionTemplate; } - String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) { - return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn)) - .replaceAll("#S", sk.subExpression); + @Override + public String expand(String optParameter) { + return expressionTemplate; } } - enum SubExprKind { + enum SubExprKind implements ComboParameter { NONE(""), SELECT_FIELD(".f"), SELECT_METHOD(".f()"), @@ -186,133 +197,78 @@ SubExprKind(String subExpression) { this.subExpression = subExpression; } + + @Override + public String expand(String optParameter) { + return subExpression; + } } public static void main(String... args) throws Exception { - for (LambdaKind lk : LambdaKind.values()) { - for (LambdaParameterName pn : LambdaParameterName.values()) { - for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { - if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) - continue; - for (LambdaParameterKind pk2 : LambdaParameterKind.values()) { - if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) - continue; - for (ModifierKind mk1 : ModifierKind.values()) { - if (mk1 != ModifierKind.NONE && lk.isShort()) - continue; - if (lk.arity() < 1 && mk1 != ModifierKind.NONE) - continue; - for (ModifierKind mk2 : ModifierKind.values()) { - if (lk.arity() < 2 && mk2 != ModifierKind.NONE) - continue; - for (SubExprKind sk : SubExprKind.values()) { - for (ExprKind ek : ExprKind.values()) { - pool.execute( - new LambdaParserTest(pk1, pk2, mk1, - mk2, lk, sk, ek, pn)); - } - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withFilter(LambdaParserTest::redundantTestFilter) + .withFilter(LambdaParserTest::badImplicitFilter) + .withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values()) + .withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values()) + .withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values()) + .withArrayDimension("MOD", (x, mod, idx) -> x.mks[idx] = mod, 2, ModifierKind.values()) + .withDimension("EXPR", ExprKind.values()) + .withDimension("SUBEXPR", SubExprKind.values()) + .run(LambdaParserTest::new); } - LambdaParameterKind pk1; - LambdaParameterKind pk2; - ModifierKind mk1; - ModifierKind mk2; + LambdaParameterKind[] pks = new LambdaParameterKind[2]; + ModifierKind[] mks = new ModifierKind[2]; LambdaKind lk; LambdaParameterName pn; - SubExprKind sk; - ExprKind ek; - JavaSource source; - DiagnosticChecker diagChecker; + + boolean badImplicitFilter() { + return !(mks[0] != ModifierKind.NONE && lk.isShort()); + } - LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2, LambdaKind lk, - SubExprKind sk, ExprKind ek, LambdaParameterName pn) { - this.pk1 = pk1; - this.pk2 = pk2; - this.mk1 = mk1; - this.mk2 = mk2; - this.lk = lk; - this.pn = pn; - this.sk = sk; - this.ek = ek; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + boolean redundantTestFilter() { + for (int i = lk.arity(); i < mks.length ; i++) { + if (mks[i].ordinal() != 0) { + return false; + } + } + for (int i = lk.arity(); i < pks.length ; i++) { + if (pks[i].ordinal() != 0) { + return false; + } + } + return true; } - class JavaSource extends SimpleJavaFileObject { - - String template = "class Test {\n" + - " SAM s = #E;\n" + - "}"; - - String source; + String template = "class Test {\n" + + " SAM s = #{EXPR};\n" + + "}"; - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#E", - ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(template) + .parse()); } - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.parse(); - } catch (Throwable ex) { - processException(ex); - return; - } - check(); - } - - void check() { - checkCount.incrementAndGet(); - - boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) || - (lk.arity() > 1 && !mk2.compatibleWith(pk2)); + void check(Result res) { + boolean errorExpected = (lk.arity() > 0 && !mks[0].compatibleWith(pks[0])) || + (lk.arity() > 1 && !mks[1].compatibleWith(pks[1])); if (lk.arity() == 2 && - (pk1.explicit() != pk2.explicit() || - pk1.isVarargs())) { + (pks[0].explicit() != pks[1].explicit() || + pks[0].isVarargs())) { errorExpected = true; } errorExpected |= pn == LambdaParameterName.UNDERSCORE && lk.arity() > 0; - if (errorExpected != diagChecker.errorFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound error: " + diagChecker.errorFound + + if (errorExpected != res.hasErrors()) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound error: " + res.hasErrors() + "\nExpected error: " + errorExpected); } } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/MethodReferenceParserTest.java --- a/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,39 +23,39 @@ /* * @test - * @bug 7115052 8003280 8006694 + * @bug 7115052 8003280 8006694 8129962 * @summary Add lambda tests * Add parser support for method references * temporarily workaround combo tests are causing time out in several platforms - * @library ../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm MethodReferenceParserTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main MethodReferenceParserTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + +public class MethodReferenceParserTest extends ComboInstance { -public class MethodReferenceParserTest - extends JavacTestingAbstractThreadedTest - implements Runnable { - - enum ReferenceKind { - METHOD_REF("#Q::#Gm"), - CONSTRUCTOR_REF("#Q::#Gnew"), + enum ReferenceKind implements ComboParameter { + METHOD_REF("#{QUAL}::#{TARGS}m"), + CONSTRUCTOR_REF("#{QUAL}::#{TARGS}new"), FALSE_REF("min < max"), - ERR_SUPER("#Q::#Gsuper"), - ERR_METH0("#Q::#Gm()"), - ERR_METH1("#Q::#Gm(X)"), - ERR_CONSTR0("#Q::#Gnew()"), - ERR_CONSTR1("#Q::#Gnew(X)"); + ERR_SUPER("#{QUAL}::#{TARGS}super"), + ERR_METH0("#{QUAL}::#{TARGS}m()"), + ERR_METH1("#{QUAL}::#{TARGS}m(X)"), + ERR_CONSTR0("#{QUAL}::#{TARGS}new()"), + ERR_CONSTR1("#{QUAL}::#{TARGS}new(X)"); String referenceTemplate; @@ -63,12 +63,6 @@ this.referenceTemplate = referenceTemplate; } - String getReferenceString(QualifierKind qk, GenericKind gk) { - return referenceTemplate - .replaceAll("#Q", qk.qualifier) - .replaceAll("#G", gk.typeParameters); - } - boolean erroneous() { switch (this) { case ERR_SUPER: @@ -80,11 +74,16 @@ default: return false; } } + + @Override + public String expand(String optParameter) { + return referenceTemplate; + } } - enum ContextKind { - ASSIGN("SAM s = #E;"), - METHOD("m(#E, i);"); + enum ContextKind implements ComboParameter { + ASSIGN("SAM s = #{EXPR};"), + METHOD("m(#{EXPR}, i);"); String contextTemplate; @@ -92,13 +91,13 @@ this.contextTemplate = contextTemplate; } - String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk, - GenericKind gk, SubExprKind sk) { - return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk)); + @Override + public String expand(String optParameter) { + return contextTemplate; } } - enum GenericKind { + enum GenericKind implements ComboParameter { NONE(""), ONE(""), TWO(""); @@ -108,9 +107,14 @@ GenericKind(String typeParameters) { this.typeParameters = typeParameters; } + + @Override + public String expand(String optParameter) { + return typeParameters; + } } - enum QualifierKind { + enum QualifierKind implements ComboParameter { THIS("this"), SUPER("super"), NEW("new Foo()"), @@ -131,15 +135,20 @@ QualifierKind(String qualifier) { this.qualifier = qualifier; } + + @Override + public String expand(String optParameter) { + return qualifier; + } } - enum ExprKind { - NONE("#R::S"), - SINGLE_PAREN1("(#R#S)"), - SINGLE_PAREN2("(#R)#S"), - DOUBLE_PAREN1("((#R#S))"), - DOUBLE_PAREN2("((#R)#S)"), - DOUBLE_PAREN3("((#R))#S"); + enum ExprKind implements ComboParameter { + NONE("#{MREF}"), + SINGLE_PAREN1("(#{MREF}#{SUBEXPR})"), + SINGLE_PAREN2("(#{MREF})#{SUBEXPR}"), + DOUBLE_PAREN1("((#{MREF}#{SUBEXPR}))"), + DOUBLE_PAREN2("((#{MREF})#{SUBEXPR})"), + DOUBLE_PAREN3("((#{MREF}))#{SUBEXPR}"); String expressionTemplate; @@ -147,14 +156,13 @@ this.expressionTemplate = expressionTemplate; } - String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) { - return expressionTemplate - .replaceAll("#R", rk.getReferenceString(qk, gk)) - .replaceAll("#S", sk.subExpression); + @Override + public String expand(String optParameter) { + return expressionTemplate; } } - enum SubExprKind { + enum SubExprKind implements ComboParameter { NONE(""), SELECT_FIELD(".f"), SELECT_METHOD(".f()"), @@ -167,100 +175,45 @@ SubExprKind(String subExpression) { this.subExpression = subExpression; } + + @Override + public String expand(String optParameter) { + return subExpression; + } } public static void main(String... args) throws Exception { - for (ReferenceKind rk : ReferenceKind.values()) { - for (QualifierKind qk : QualifierKind.values()) { - for (GenericKind gk : GenericKind.values()) { - for (SubExprKind sk : SubExprKind.values()) { - for (ExprKind ek : ExprKind.values()) { - for (ContextKind ck : ContextKind.values()) { - pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck)); - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withDimension("MREF", (x, ref) -> x.rk = ref, ReferenceKind.values()) + .withDimension("QUAL", QualifierKind.values()) + .withDimension("TARGS", GenericKind.values()) + .withDimension("EXPR", ExprKind.values()) + .withDimension("SUBEXPR", SubExprKind.values()) + .withDimension("CTX", ContextKind.values()) + .run(MethodReferenceParserTest::new); } ReferenceKind rk; - QualifierKind qk; - GenericKind gk; - SubExprKind sk; - ExprKind ek; - ContextKind ck; - JavaSource source; - DiagnosticChecker diagChecker; - MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) { - this.rk = rk; - this.qk = qk; - this.gk = gk; - this.sk = sk; - this.ek = ek; - this.ck = ck; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + String template = "class Test {\n" + + " void test() {\n" + + " #{CTX}\n" + + " }" + + "}"; + + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(template) + .parse()); } - class JavaSource extends SimpleJavaFileObject { - - String template = "class Test {\n" + - " void test() {\n" + - " #C\n" + - " }" + - "}"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - @Override - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.parse(); - } catch (Throwable ex) { - processException(ex); - return; - } - check(); - } - - void check() { - checkCount.incrementAndGet(); - - if (diagChecker.errorFound != rk.erroneous()) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound error: " + diagChecker.errorFound + + void check(Result res) { + if (res.hasErrors() != rk.erroneous()) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound error: " + res.hasErrors() + "\nExpected error: " + rk.erroneous()); } } - - static class DiagnosticChecker implements javax.tools.DiagnosticListener { - - boolean errorFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8129547 + * @summary Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs + * @library /tools/javac/lib + * @modules jdk.jdeps/com.sun.tools.classfile + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + */ + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; + +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreeScanner; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.BootstrapMethods_attribute; +import com.sun.tools.classfile.ClassFile; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Names; + +import static com.sun.tools.javac.jvm.ClassFile.*; + +public class TestBootstrapMethodsCount { + + public static void main(String... args) throws Exception { + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + new TestBootstrapMethodsCount().run(comp); + } + + DiagChecker dc; + + TestBootstrapMethodsCount() { + dc = new DiagChecker(); + } + + public void run(JavaCompiler comp) { + JavaSource source = new JavaSource(); + JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, null, dc, + Arrays.asList("-g"), null, Arrays.asList(source)); + Context context = ct.getContext(); + Symtab syms = Symtab.instance(context); + Names names = Names.instance(context); + Types types = Types.instance(context); + ct.addTaskListener(new Indifier(syms, names, types)); + try { + ct.generate(); + } catch (Throwable t) { + t.printStackTrace(); + throw new AssertionError( + String.format("Error thrown when compiling following code\n%s", + source.source)); + } + if (dc.diagFound) { + throw new AssertionError( + String.format("Diags found when compiling following code\n%s\n\n%s", + source.source, dc.printDiags())); + } + verifyBytecode(); + } + + void verifyBytecode() { + File compiledTest = new File("Test.class"); + try { + ClassFile cf = ClassFile.read(compiledTest); + BootstrapMethods_attribute bsm_attr = + (BootstrapMethods_attribute)cf + .getAttribute(Attribute.BootstrapMethods); + int length = bsm_attr.bootstrap_method_specifiers.length; + if (length != 1) { + throw new Error("Bad number of method specifiers " + + "in BootstrapMethods attribute: " + length); + } + } catch (Exception e) { + e.printStackTrace(); + throw new Error("error reading " + compiledTest +": " + e); + } + } + + class JavaSource extends SimpleJavaFileObject { + + static final String source = "import java.lang.invoke.*;\n" + + "class Bootstrap {\n" + + " public static CallSite bsm(MethodHandles.Lookup lookup, " + + "String name, MethodType methodType) {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "class Test {\n" + + " void m1() { }\n" + + " void m2(Object arg1) { }\n" + + " void test1() {\n" + + " Object o = this; // marker statement \n" + + " m1();\n" + + " }\n" + + " void test2(Object arg1) {\n" + + " Object o = this; // marker statement \n" + + " m2(arg1);\n" + + " }\n" + + "}"; + + JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + class Indifier extends TreeScanner implements TaskListener { + + MethodSymbol bsm; + Symtab syms; + Names names; + Types types; + + Indifier(Symtab syms, Names names, Types types) { + this.syms = syms; + this.names = names; + this.types = types; + } + + @Override + public void started(TaskEvent e) { + //do nothing + } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) { + scan(e.getCompilationUnit(), null); + } + } + + @Override + public Void visitMethodInvocation(MethodInvocationTree node, Void p) { + super.visitMethodInvocation(node, p); + JCMethodInvocation apply = (JCMethodInvocation)node; + JCIdent ident = (JCIdent)apply.meth; + Symbol oldSym = ident.sym; + if (!oldSym.isConstructor()) { + ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, + oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]); + } + return null; + } + + @Override + public Void visitMethod(MethodTree node, Void p) { + super.visitMethod(node, p); + if (node.getName().toString().equals("bsm")) { + bsm = ((JCMethodDecl)node).sym; + } + return null; + } + } + + static class DiagChecker + implements javax.tools.DiagnosticListener { + + boolean diagFound; + ArrayList diags = new ArrayList<>(); + + public void report(Diagnostic diagnostic) { + diags.add(diagnostic.getMessage(Locale.getDefault())); + diagFound = true; + } + + String printDiags() { + StringBuilder buf = new StringBuilder(); + for (String s : diags) { + buf.append(s); + buf.append("\n"); + } + return buf.toString(); + } + } + +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/TestInvokeDynamic.java --- a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,33 +23,27 @@ /* * @test - * @bug 7194586 8003280 8006694 8010404 + * @bug 7194586 8003280 8006694 8010404 8129962 * @summary Add lambda tests * Add back-end support for invokedynamic * temporarily workaround combo tests are causing time out in several platforms - * @library ../lib + * @library /tools/javac/lib * @modules jdk.jdeps/com.sun.tools.classfile * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.jvm * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm TestInvokeDynamic + * @build combo.ComboTestHelper + * @run main TestInvokeDynamic */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; +import java.io.InputStream; -import java.io.File; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.MethodTree; @@ -78,13 +72,17 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Names; +import combo.ComboParameter; +import combo.ComboTask; +import combo.ComboTestHelper; +import combo.ComboInstance; +import combo.ComboTask.Result; + import static com.sun.tools.javac.jvm.ClassFile.*; -public class TestInvokeDynamic - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class TestInvokeDynamic extends ComboInstance { - enum StaticArgumentKind { + enum StaticArgumentKind implements ComboParameter { STRING("Hello!", "String", "Ljava/lang/String;") { @Override boolean check(CPInfo cpInfo) throws Exception { @@ -189,88 +187,91 @@ throw new AssertionError(); } } + + @Override + public String expand(String optParameter) { + return sourceTypeStr; + } } - enum StaticArgumentsArity { - ZERO(0), - ONE(1), - TWO(2), - THREE(3); + enum StaticArgumentsArity implements ComboParameter { + ZERO(0, ""), + ONE(1, ",#{SARG[0]} s1"), + TWO(2, ",#{SARG[0]} s1, #{SARG[1]} s2"), + THREE(3, ",#{SARG[0]} s1, #{SARG[1]} s2, #{SARG[2]} s3"); int arity; + String argsTemplate; - StaticArgumentsArity(int arity) { + StaticArgumentsArity(int arity, String argsTemplate) { this.arity = arity; + this.argsTemplate = argsTemplate; + } + + @Override + public String expand(String optParameter) { + return argsTemplate; } } public static void main(String... args) throws Exception { - for (StaticArgumentsArity arity : StaticArgumentsArity.values()) { - if (arity.arity == 0) { - pool.execute(new TestInvokeDynamic(arity)); - } else { - for (StaticArgumentKind sak1 : StaticArgumentKind.values()) { - if (arity.arity == 1) { - pool.execute(new TestInvokeDynamic(arity, sak1)); - } else { - for (StaticArgumentKind sak2 : StaticArgumentKind.values()) { - if (arity.arity == 2) { - pool.execute(new TestInvokeDynamic(arity, sak1, sak2)); - } else { - for (StaticArgumentKind sak3 : StaticArgumentKind.values()) { - pool.execute( - new TestInvokeDynamic(arity, sak1, sak2, sak3)); - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withFilter(TestInvokeDynamic::redundantTestFilter) + .withDimension("SARGS", (x, arity) -> x.arity = arity, StaticArgumentsArity.values()) + .withArrayDimension("SARG", (x, arg, idx) -> x.saks[idx] = arg, 3, StaticArgumentKind.values()) + .run(TestInvokeDynamic::new); } StaticArgumentsArity arity; - StaticArgumentKind[] saks; - DiagChecker dc; + StaticArgumentKind[] saks = new StaticArgumentKind[3]; - TestInvokeDynamic(StaticArgumentsArity arity, StaticArgumentKind... saks) { - this.arity = arity; - this.saks = saks; - dc = new DiagChecker(); + boolean redundantTestFilter() { + for (int i = arity.arity ; i < saks.length ; i++) { + if (saks[i].ordinal() != 0) { + return false; + } + } + return true; } - public void run() { - int id = checkCount.incrementAndGet(); - JavaSource source = new JavaSource(id); - JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc, - Arrays.asList("-g"), null, Arrays.asList(source)); + final String source_template = + "import java.lang.invoke.*;\n" + + "class Test {\n" + + " void m() { }\n" + + " void test() {\n" + + " Object o = this; // marker statement \n" + + " m();\n" + + " }\n" + + "}\n" + + "class Bootstrap {\n" + + " public static CallSite bsm(MethodHandles.Lookup lookup, " + + "String name, MethodType methodType #{SARGS}) {\n" + + " return null;\n" + + " }\n" + + "}"; + + @Override + public void doWork() throws IOException { + ComboTask comboTask = newCompilationTask() + .withOption("-g") + .withSourceFromTemplate(source_template); + + JavacTaskImpl ct = (JavacTaskImpl)comboTask.getTask(); Context context = ct.getContext(); Symtab syms = Symtab.instance(context); Names names = Names.instance(context); Types types = Types.instance(context); ct.addTaskListener(new Indifier(syms, names, types)); - try { - ct.generate(); - } catch (Throwable t) { - t.printStackTrace(); - throw new AssertionError( - String.format("Error thrown when compiling following code\n%s", - source.source)); - } - if (dc.diagFound) { - throw new AssertionError( - String.format("Diags found when compiling following code\n%s\n\n%s", - source.source, dc.printDiags())); - } - verifyBytecode(id); + verifyBytecode(comboTask.generate()); } - void verifyBytecode(int id) { - File compiledTest = new File(String.format("Test%d.class", id)); - try { - ClassFile cf = ClassFile.read(compiledTest); + void verifyBytecode(Result> res) { + if (res.hasErrors()) { + fail("Diags found when compiling instance: " + res.compilationInfo()); + return; + } + try (InputStream is = res.get().iterator().next().openInputStream()){ + ClassFile cf = ClassFile.read(is); Method testMethod = null; for (Method m : cf.methods) { if (m.getName(cf.constant_pool).equals("test")) { @@ -279,12 +280,14 @@ } } if (testMethod == null) { - throw new Error("Test method not found"); + fail("Test method not found"); + return; } Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code); if (testMethod == null) { - throw new Error("Code attribute for test() method not found"); + fail("Code attribute for test() method not found"); + return; } int bsmIdx = -1; @@ -296,37 +299,39 @@ .constant_pool.get(i.getShort(1)); bsmIdx = indyInfo.bootstrap_method_attr_index; if (!indyInfo.getNameAndTypeInfo().getType().equals("()V")) { - throw new - AssertionError("type mismatch for CONSTANT_InvokeDynamic_info"); + fail("type mismatch for CONSTANT_InvokeDynamic_info"); + return; } } } if (bsmIdx == -1) { - throw new Error("Missing invokedynamic in generated code"); + fail("Missing invokedynamic in generated code"); + return; } BootstrapMethods_attribute bsm_attr = (BootstrapMethods_attribute)cf .getAttribute(Attribute.BootstrapMethods); if (bsm_attr.bootstrap_method_specifiers.length != 1) { - throw new Error("Bad number of method specifiers " + + fail("Bad number of method specifiers " + "in BootstrapMethods attribute"); + return; } BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec = bsm_attr.bootstrap_method_specifiers[0]; if (bsm_spec.bootstrap_arguments.length != arity.arity) { - throw new Error("Bad number of static invokedynamic args " + + fail("Bad number of static invokedynamic args " + "in BootstrapMethod attribute"); + return; } - int count = 0; - for (StaticArgumentKind sak : saks) { - if (!sak.check(cf.constant_pool - .get(bsm_spec.bootstrap_arguments[count]))) { - throw new Error("Bad static argument value " + sak); + for (int i = 0 ; i < arity.arity ; i++) { + if (!saks[i].check(cf.constant_pool + .get(bsm_spec.bootstrap_arguments[i]))) { + fail("Bad static argument value " + saks[i]); + return; } - count++; } CONSTANT_MethodHandle_info bsm_handle = @@ -334,7 +339,8 @@ .get(bsm_spec.bootstrap_method_ref); if (bsm_handle.reference_kind != RefKind.REF_invokeStatic) { - throw new Error("Bad kind on boostrap method handle"); + fail("Bad kind on boostrap method handle"); + return; } CONSTANT_Methodref_info bsm_ref = @@ -342,88 +348,51 @@ .get(bsm_handle.reference_index); if (!bsm_ref.getClassInfo().getName().equals("Bootstrap")) { - throw new Error("Bad owner of boostrap method"); + fail("Bad owner of boostrap method"); + return; } if (!bsm_ref.getNameAndTypeInfo().getName().equals("bsm")) { - throw new Error("Bad boostrap method name"); + fail("Bad boostrap method name"); + return; } if (!bsm_ref.getNameAndTypeInfo() .getType().equals(asBSMSignatureString())) { - throw new Error("Bad boostrap method type" + + fail("Bad boostrap method type" + bsm_ref.getNameAndTypeInfo().getType() + " " + asBSMSignatureString()); + return; } LineNumberTable_attribute lnt = (LineNumberTable_attribute)ea.attributes.get(Attribute.LineNumberTable); if (lnt == null) { - throw new Error("No LineNumberTable attribute"); + fail("No LineNumberTable attribute"); + return; } if (lnt.line_number_table_length != 3) { - throw new Error("Wrong number of entries in LineNumberTable"); + fail("Wrong number of entries in LineNumberTable"); + return; } } catch (Exception e) { e.printStackTrace(); - throw new Error("error reading " + compiledTest +": " + e); + fail("error reading classfile: " + res.compilationInfo()); + return; } } String asBSMSignatureString() { StringBuilder buf = new StringBuilder(); buf.append("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;"); - for (StaticArgumentKind sak : saks) { - buf.append(sak.bytecodeTypeStr); + for (int i = 0 ; i < arity.arity ; i++) { + buf.append(saks[i].bytecodeTypeStr); } buf.append(")Ljava/lang/invoke/CallSite;"); return buf.toString(); } - class JavaSource extends SimpleJavaFileObject { - - static final String source_template = "import java.lang.invoke.*;\n" + - "class Bootstrap {\n" + - " public static CallSite bsm(MethodHandles.Lookup lookup, " + - "String name, MethodType methodType #SARGS) {\n" + - " return null;\n" + - " }\n" + - "}\n" + - "class Test#ID {\n" + - " void m() { }\n" + - " void test() {\n" + - " Object o = this; // marker statement \n" + - " m();\n" + - " }\n" + - "}"; - - String source; - - JavaSource(int id) { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = source_template.replace("#SARGS", asSignatureString()) - .replace("#ID", String.valueOf(id)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - - String asSignatureString() { - int count = 0; - StringBuilder buf = new StringBuilder(); - for (StaticArgumentKind sak : saks) { - buf.append(","); - buf.append(sak.sourceTypeStr); - buf.append(' '); - buf.append(String.format("x%d", count++)); - } - return buf.toString(); - } - } - class Indifier extends TreeScanner implements TaskListener { MethodSymbol bsm; @@ -475,26 +444,4 @@ return null; } } - - static class DiagChecker - implements javax.tools.DiagnosticListener { - - boolean diagFound; - ArrayList diags = new ArrayList<>(); - - public void report(Diagnostic diagnostic) { - diags.add(diagnostic.getMessage(Locale.getDefault())); - diagFound = true; - } - - String printDiags() { - StringBuilder buf = new StringBuilder(); - for (String s : diags) { - buf.append(s); - buf.append("\n"); - } - return buf.toString(); - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/TestLambdaToMethodStats.java --- a/langtools/test/tools/javac/lambda/TestLambdaToMethodStats.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/TestLambdaToMethodStats.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,34 +23,35 @@ /* * @test - * @bug 8013576 + * @bug 8013576 8129962 * @summary Add stat support to LambdaToMethod - * @library ../lib + * @library /tools/javac/lib * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm TestLambdaToMethodStats + * @build combo.ComboTestHelper + * @run main TestLambdaToMethodStats */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import java.net.URI; -import java.util.Arrays; +import java.io.IOException; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; import com.sun.tools.javac.api.ClientCodeWrapper; -import com.sun.tools.javac.util.JCDiagnostic; -public class TestLambdaToMethodStats - extends JavacTestingAbstractThreadedTest - implements Runnable { +import com.sun.tools.javac.util.List; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - enum ExprKind { +public class TestLambdaToMethodStats extends ComboInstance { + + enum ExprKind implements ComboParameter { LAMBDA("()->null"), MREF1("this::g"), MREF2("this::h"); @@ -60,9 +61,14 @@ ExprKind(String exprStr) { this.exprStr = exprStr; } + + @Override + public String expand(String optParameter) { + return exprStr; + } } - enum TargetKind { + enum TargetKind implements ComboParameter { IMPLICIT(""), SERIALIZABLE("(A & java.io.Serializable)"); @@ -71,124 +77,89 @@ TargetKind(String targetStr) { this.targetStr = targetStr; } + + @Override + public String expand(String optParameter) { + return targetStr; + } + } + + enum DiagnosticKind { + LAMBDA_STAT("compiler.note.lambda.stat", true, false), + MREF_STAT("compiler.note.mref.stat", false, false), + MREF_STAT1("compiler.note.mref.stat.1", false, true); + + String code; + boolean lambda; + boolean bridge; + + DiagnosticKind(String code, boolean lambda, boolean bridge) { + this.code = code; + this.lambda = lambda; + this.bridge = bridge; + } } public static void main(String... args) throws Exception { - for (ExprKind ek : ExprKind.values()) { - for (TargetKind tk : TargetKind.values()) { - pool.execute(new TestLambdaToMethodStats(ek, tk)); - } - } - - checkAfterExec(true); + new ComboTestHelper() + .withDimension("EXPR", (x, expr) -> x.ek = expr, ExprKind.values()) + .withDimension("CAST", (x, target) -> x.tk = target, TargetKind.values()) + .run(TestLambdaToMethodStats::new); } ExprKind ek; TargetKind tk; - JavaSource source; - DiagnosticChecker diagChecker; - - TestLambdaToMethodStats(ExprKind ek, TargetKind tk) { - this.ek = ek; - this.tk = tk; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); + String template = "interface A {\n" + + " Object o();\n" + + "}\n" + + "class Test {\n" + + " A a = #{CAST}#{EXPR};\n" + + " Object g() { return null; }\n" + + " Object h(Object... o) { return null; }\n" + + "}"; + + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withOption("-XDdumpLambdaToMethodStats") + .withSourceFromTemplate(template) + .generate()); } - class JavaSource extends SimpleJavaFileObject { - - String template = "interface A {\n" + - " Object o();\n" + - "}\n" + - "class Test {\n" + - " A a = #C#E;\n" + - " Object g() { return null; }\n" + - " Object h(Object... o) { return null; }\n" + - "}"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#E", ek.exprStr) - .replaceAll("#C", tk.targetStr); + void check(Result res) { + DiagnosticKind diag = null; + boolean altMetafactory = false; + for (DiagnosticKind dk : DiagnosticKind.values()) { + List> jcDiag = res.diagnosticsForKey(dk.code); + if (jcDiag.nonEmpty()) { + diag = dk; + ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = + (ClientCodeWrapper.DiagnosticSourceUnwrapper)jcDiag.head; + altMetafactory = (Boolean)dsu.d.getArgs()[0]; + break; + } } - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + if (diag == null) { + fail("No diagnostic found; " + res.compilationInfo()); } - } - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - Arrays.asList("-XDdumpLambdaToMethodStats"), - null, Arrays.asList(source)); - try { - ct.generate(); - } catch (Throwable ex) { - throw new - AssertionError("Error thron when analyzing the following source:\n" + - source.getCharContent(true)); - } - check(); - } - - void check() { - checkCount.incrementAndGet(); - - boolean error = diagChecker.lambda != + boolean error = diag.lambda != (ek == ExprKind.LAMBDA); - error |= diagChecker.bridge != + error |= diag.bridge != (ek == ExprKind.MREF2); - error |= diagChecker.altMetafactory != + error |= altMetafactory != (tk == TargetKind.SERIALIZABLE); if (error) { - throw new AssertionError("Bad stat diagnostic found for source\n" + - "lambda = " + diagChecker.lambda + "\n" + - "bridge = " + diagChecker.bridge + "\n" + - "altMF = " + diagChecker.altMetafactory + "\n" + - source.source); - } - } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean altMetafactory; - boolean bridge; - boolean lambda; - - public void report(Diagnostic diagnostic) { - try { - if (diagnostic.getKind() == Diagnostic.Kind.NOTE) { - switch (diagnostic.getCode()) { - case "compiler.note.lambda.stat": - lambda = true; - break; - case "compiler.note.mref.stat": - lambda = false; - bridge = false; - break; - case "compiler.note.mref.stat.1": - lambda = false; - bridge = true; - break; - default: - throw new AssertionError("unexpected note: " + diagnostic.getCode()); - } - ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = - (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic; - altMetafactory = (Boolean)dsu.d.getArgs()[0]; - } - } catch (RuntimeException t) { - t.printStackTrace(); - throw t; - } + fail("Bad stat diagnostic found for source\n" + + "lambda = " + diag.lambda + "\n" + + "bridge = " + diag.bridge + "\n" + + "altMF = " + altMetafactory + "\n" + + res.compilationInfo()); } } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/bytecode/TestLambdaBytecode.java --- a/langtools/test/tools/javac/lambda/bytecode/TestLambdaBytecode.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/bytecode/TestLambdaBytecode.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,18 +23,20 @@ /* * @test - * @bug 8009649 + * @bug 8009649 8129962 * @summary Lambda back-end should generate invokespecial for method handles referring to private instance methods - * @library ../../lib + * @library /tools/javac/lib * @modules jdk.jdeps/com.sun.tools.classfile * jdk.compiler/com.sun.tools.javac.api - * @build JavacTestingAbstractThreadedTest - * @run main/othervm TestLambdaBytecode + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main TestLambdaBytecode */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - import com.sun.tools.classfile.Attribute; import com.sun.tools.classfile.BootstrapMethods_attribute; import com.sun.tools.classfile.ClassFile; @@ -43,26 +45,22 @@ import com.sun.tools.classfile.Instruction; import com.sun.tools.classfile.Method; -import com.sun.tools.javac.api.JavacTaskImpl; - +import java.io.IOException; +import java.io.InputStream; -import java.io.File; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import static com.sun.tools.javac.jvm.ClassFile.*; +public class TestLambdaBytecode extends ComboInstance { -public class TestLambdaBytecode - extends JavacTestingAbstractThreadedTest - implements Runnable { + static final int MF_ARITY = 3; + static final String MH_SIG = "()V"; - enum ClassKind { + enum ClassKind implements ComboParameter { CLASS("class"), INTERFACE("interface"); @@ -71,9 +69,14 @@ ClassKind(String classStr) { this.classStr = classStr; } + + @Override + public String expand(String optParameter) { + return classStr; + } } - enum AccessKind { + enum AccessKind implements ComboParameter { PUBLIC("public"), PRIVATE("private"); @@ -82,9 +85,14 @@ AccessKind(String accessStr) { this.accessStr = accessStr; } + + @Override + public String expand(String optParameter) { + return accessStr; + } } - enum StaticKind { + enum StaticKind implements ComboParameter { STATIC("static"), INSTANCE(""); @@ -93,9 +101,14 @@ StaticKind(String staticStr) { this.staticStr = staticStr; } + + @Override + public String expand(String optParameter) { + return staticStr; + } } - enum DefaultKind { + enum DefaultKind implements ComboParameter { DEFAULT("default"), NO_DEFAULT(""); @@ -104,15 +117,10 @@ DefaultKind(String defaultStr) { this.defaultStr = defaultStr; } - } - enum ExprKind { - LAMBDA("Runnable r = ()->{ target(); };"); - - String exprString; - - ExprKind(String exprString) { - this.exprString = exprString; + @Override + public String expand(String optParameter) { + return defaultStr; } } @@ -155,83 +163,53 @@ return true; } } - - String mods() { - StringBuilder buf = new StringBuilder(); - buf.append(ak.accessStr); - buf.append(' '); - buf.append(sk.staticStr); - buf.append(' '); - buf.append(dk.defaultStr); - return buf.toString(); - } } public static void main(String... args) throws Exception { - for (ClassKind ck : ClassKind.values()) { - for (AccessKind ak1 : AccessKind.values()) { - for (StaticKind sk1 : StaticKind.values()) { - for (DefaultKind dk1 : DefaultKind.values()) { - for (AccessKind ak2 : AccessKind.values()) { - for (StaticKind sk2 : StaticKind.values()) { - for (DefaultKind dk2 : DefaultKind.values()) { - for (ExprKind ek : ExprKind.values()) { - pool.execute(new TestLambdaBytecode(ck, ak1, ak2, sk1, sk2, dk1, dk2, ek)); - } - } - } - } - } - } - } - } - - checkAfterExec(); + new ComboTestHelper() + .withDimension("CLASSKIND", (x, ck) -> x.ck = ck, ClassKind.values()) + .withArrayDimension("ACCESS", (x, acc, idx) -> x.accessKinds[idx] = acc, 2, AccessKind.values()) + .withArrayDimension("STATIC", (x, sk, idx) -> x.staticKinds[idx] = sk, 2, StaticKind.values()) + .withArrayDimension("DEFAULT", (x, dk, idx) -> x.defaultKinds[idx] = dk, 2, DefaultKind.values()) + .run(TestLambdaBytecode::new, TestLambdaBytecode::init); } + ClassKind ck; + AccessKind[] accessKinds = new AccessKind[2]; + StaticKind[] staticKinds = new StaticKind[2]; + DefaultKind[] defaultKinds = new DefaultKind[2]; MethodKind mk1, mk2; - ExprKind ek; - DiagChecker dc; - TestLambdaBytecode(ClassKind ck, AccessKind ak1, AccessKind ak2, StaticKind sk1, - StaticKind sk2, DefaultKind dk1, DefaultKind dk2, ExprKind ek) { - mk1 = new MethodKind(ck, ak1, sk1, dk1); - mk2 = new MethodKind(ck, ak2, sk2, dk2); - this.ek = ek; - dc = new DiagChecker(); + void init() { + mk1 = new MethodKind(ck, accessKinds[0], staticKinds[0], defaultKinds[0]); + mk2 = new MethodKind(ck, accessKinds[1], staticKinds[1], defaultKinds[1]); } - public void run() { - int id = checkCount.incrementAndGet(); - JavaSource source = new JavaSource(id); - JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc, - null, null, Arrays.asList(source)); - try { - ct.generate(); - } catch (Throwable t) { - t.printStackTrace(); - throw new AssertionError( - String.format("Error thrown when compiling following code\n%s", - source.source)); - } - if (dc.diagFound) { + String source_template = + "#{CLASSKIND} Test {\n" + + " #{ACCESS[0]} #{STATIC[0]} #{DEFAULT[0]} void test() { Runnable r = ()->{ target(); }; }\n" + + " #{ACCESS[1]} #{STATIC[1]} #{DEFAULT[1]} void target() { }\n" + + "}\n"; + + @Override + public void doWork() throws IOException { + verifyBytecode(newCompilationTask() + .withSourceFromTemplate(source_template) + .generate()); + } + + void verifyBytecode(Result> res) { + if (res.hasErrors()) { boolean errorExpected = !mk1.isOK() || !mk2.isOK(); errorExpected |= mk1.isStatic() && !mk2.isStatic(); if (!errorExpected) { - throw new AssertionError( - String.format("Diags found when compiling following code\n%s\n\n%s", - source.source, dc.printDiags())); + fail("Diags found when compiling instance; " + res.compilationInfo()); } return; } - verifyBytecode(id, source); - } - - void verifyBytecode(int id, JavaSource source) { - File compiledTest = new File(String.format("Test%d.class", id)); - try { - ClassFile cf = ClassFile.read(compiledTest); + try (InputStream is = res.get().iterator().next().openInputStream()) { + ClassFile cf = ClassFile.read(is); Method testMethod = null; for (Method m : cf.methods) { if (m.getName(cf.constant_pool).equals("test")) { @@ -240,12 +218,14 @@ } } if (testMethod == null) { - throw new Error("Test method not found"); + fail("Test method not found"); + return; } Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code); if (testMethod == null) { - throw new Error("Code attribute for test() method not found"); + fail("Code attribute for test() method not found"); + return; } int bsmIdx = -1; @@ -256,29 +236,34 @@ (CONSTANT_InvokeDynamic_info)cf .constant_pool.get(i.getShort(1)); bsmIdx = indyInfo.bootstrap_method_attr_index; - if (!indyInfo.getNameAndTypeInfo().getType().equals(makeIndyType(id))) { - throw new - AssertionError("type mismatch for CONSTANT_InvokeDynamic_info " + source.source + "\n" + indyInfo.getNameAndTypeInfo().getType() + "\n" + makeIndyType(id)); + if (!indyInfo.getNameAndTypeInfo().getType().equals(makeIndyType())) { + fail("type mismatch for CONSTANT_InvokeDynamic_info " + + res.compilationInfo() + "\n" + indyInfo.getNameAndTypeInfo().getType() + + "\n" + makeIndyType()); + return; } } } if (bsmIdx == -1) { - throw new Error("Missing invokedynamic in generated code"); + fail("Missing invokedynamic in generated code"); + return; } BootstrapMethods_attribute bsm_attr = (BootstrapMethods_attribute)cf .getAttribute(Attribute.BootstrapMethods); if (bsm_attr.bootstrap_method_specifiers.length != 1) { - throw new Error("Bad number of method specifiers " + + fail("Bad number of method specifiers " + "in BootstrapMethods attribute"); + return; } BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec = bsm_attr.bootstrap_method_specifiers[0]; if (bsm_spec.bootstrap_arguments.length != MF_ARITY) { - throw new Error("Bad number of static invokedynamic args " + + fail("Bad number of static invokedynamic args " + "in BootstrapMethod attribute"); + return; } CONSTANT_MethodHandle_info mh = @@ -294,74 +279,27 @@ } if (!kindOK) { - throw new Error("Bad invoke kind in implementation method handle"); + fail("Bad invoke kind in implementation method handle"); + return; } if (!mh.getCPRefInfo().getNameAndTypeInfo().getType().toString().equals(MH_SIG)) { - throw new Error("Type mismatch in implementation method handle"); + fail("Type mismatch in implementation method handle"); + return; } } catch (Exception e) { e.printStackTrace(); - throw new Error("error reading " + compiledTest +": " + e); + fail("error reading " + res.compilationInfo() + ": " + e); } } - String makeIndyType(int id) { + + String makeIndyType() { StringBuilder buf = new StringBuilder(); buf.append("("); if (!mk2.isStatic()) { - buf.append(String.format("LTest%d;", id)); + buf.append("LTest;"); } buf.append(")Ljava/lang/Runnable;"); return buf.toString(); } - - static final int MF_ARITY = 3; - static final String MH_SIG = "()V"; - - class JavaSource extends SimpleJavaFileObject { - - static final String source_template = - "#CK Test#ID {\n" + - " #MOD1 void test() { #EK }\n" + - " #MOD2 void target() { }\n" + - "}\n"; - - String source; - - JavaSource(int id) { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = source_template.replace("#CK", mk1.ck.classStr) - .replace("#MOD1", mk1.mods()) - .replace("#MOD2", mk2.mods()) - .replace("#EK", ek.exprString) - .replace("#ID", String.valueOf(id)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - static class DiagChecker - implements javax.tools.DiagnosticListener { - - boolean diagFound; - ArrayList diags = new ArrayList<>(); - - public void report(Diagnostic diagnostic) { - diags.add(diagnostic.getMessage(Locale.getDefault())); - diagFound = true; - } - - String printDiags() { - StringBuilder buf = new StringBuilder(); - for (String s : diags) { - buf.append(s); - buf.append("\n"); - } - return buf.toString(); - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java --- a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,34 +23,36 @@ /* * @test - * @bug 8003280 8006694 + * @bug 8003280 8006694 8129962 * @summary Add lambda tests * Automatic test for checking correctness of structural most specific test routine * temporarily workaround combo tests are causing time out in several platforms - * @library ../../lib + * @library /tools/javac/lib * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm/timeout=600 StructuralMostSpecificTest + * @build combo.ComboTestHelper + + * @run main StructuralMostSpecificTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import java.net.URI; -import java.util.Arrays; +import javax.lang.model.element.Element; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; import com.sun.tools.javac.api.ClientCodeWrapper; import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.List; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -public class StructuralMostSpecificTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class StructuralMostSpecificTest extends ComboInstance { - enum RetTypeKind { + enum RetTypeKind implements ComboParameter { SHORT("short"), INT("int"), OBJECT("Object"), @@ -76,9 +78,13 @@ /* INTEGER */ { false , false , true , true , false , false }, /* VOID */ { false , false , false , false , true , true }, /* J_L_VOID */{ false , false , true , false , false , true } }; + + public String expand(String optParameter) { + return retTypeStr; + } } - enum ArgTypeKind { + enum ArgTypeKind implements ComboParameter { SHORT("short"), INT("int"), BOOLEAN("boolean"), @@ -91,9 +97,13 @@ ArgTypeKind(String typeStr) { this.argTypeStr = typeStr; } + + public String expand(String optParameter) { + return argTypeStr; + } } - enum ExceptionKind { + enum ExceptionKind implements ComboParameter { NONE(""), EXCEPTION("throws Exception"), SQL_EXCEPTION("throws java.sql.SQLException"), @@ -104,9 +114,13 @@ ExceptionKind(String exceptionStr) { this.exceptionStr = exceptionStr; } + + public String expand(String optParameter) { + return exceptionStr; + } } - enum LambdaReturnKind { + enum LambdaReturnKind implements ComboParameter { VOID("return;"), SHORT("return (short)0;"), INT("return 0;"), @@ -144,118 +158,72 @@ /* INTEGER */ { false , false , true , false , false }, /* VOID */ { false , false , false , false , false }, /* J_L_VOID */{ true , false , false , false , false } }; - } - public static void main(String... args) throws Exception { - for (LambdaReturnKind lrk : LambdaReturnKind.values()) { - for (RetTypeKind rk1 : RetTypeKind.values()) { - for (RetTypeKind rk2 : RetTypeKind.values()) { - for (ExceptionKind ek1 : ExceptionKind.values()) { - for (ExceptionKind ek2 : ExceptionKind.values()) { - for (ArgTypeKind ak11 : ArgTypeKind.values()) { - for (ArgTypeKind ak12 : ArgTypeKind.values()) { - pool.execute( - new StructuralMostSpecificTest(lrk, rk1, - rk2, ek1, ek2, ak11, ak12)); - } - } - } - } - } - } - } - - checkAfterExec(); - } - - LambdaReturnKind lrk; - RetTypeKind rt1, rt2; - ArgTypeKind ak1, ak2; - ExceptionKind ek1, ek2; - JavaSource source; - DiagnosticChecker diagChecker; - - StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2, - ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) { - this.lrk = lrk; - this.rt1 = rt1; - this.rt2 = rt2; - this.ek1 = ek1; - this.ek2 = ek2; - this.ak1 = ak1; - this.ak2 = ak2; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); - } - - class JavaSource extends SimpleJavaFileObject { - - String template = "interface SAM1 {\n" + - " #R1 m(#A1 a1) #E1;\n" + - "}\n" + - "interface SAM2 {\n" + - " #R2 m(#A2 a1) #E2;\n" + - "}\n" + - "class Test {\n" + - " void m(SAM1 s) { }\n" + - " void m(SAM2 s) { }\n" + - " { m((#A1 x)->{ #LR }); }\n" + - "}\n"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#LR", lrk.retStr) - .replaceAll("#R1", rt1.retTypeStr) - .replaceAll("#R2", rt2.retTypeStr) - .replaceAll("#A1", ak1.argTypeStr) - .replaceAll("#A2", ak2.argTypeStr) - .replaceAll("#E1", ek1.exceptionStr) - .replaceAll("#E2", ek2.exceptionStr); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + public String expand(String optParameter) { + return retStr; } } - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"), - null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable ex) { - throw new - AssertionError("Error thron when analyzing the following source:\n" + - source.getCharContent(true)); - } - check(); + static final String sourceTemplate = + "interface SAM1 {\n" + + " #{RET[0]} m(#{ARG[0]} a1) #{EX[0]};\n" + + "}\n" + + "interface SAM2 {\n" + + " #{RET[1]} m(#{ARG[1]} a1) #{EX[1]};\n" + + "}\n" + + "class Test {\n" + + " void m(SAM1 s) { }\n" + + " void m(SAM2 s) { }\n" + + " { m((#{ARG[0]} x)->{ #{EXPR} }); }\n" + + "}\n"; + + public static void main(String... args) throws Exception { + new ComboTestHelper() + .withFilter(StructuralMostSpecificTest::hasSameArguments) + .withFilter(StructuralMostSpecificTest::hasCompatibleReturns) + .withFilter(StructuralMostSpecificTest::hasSameOverloadPhase) + .withDimension("EXPR", (x, expr) -> x.lambdaReturnKind = expr, LambdaReturnKind.values()) + .withArrayDimension("RET", (x, ret, idx) -> x.returnType[idx] = ret, 2, RetTypeKind.values()) + .withArrayDimension("EX", 2, ExceptionKind.values()) + .withArrayDimension("ARG", (x, arg, idx) -> x.argumentKind[idx] = arg, 2, ArgTypeKind.values()) + .run(StructuralMostSpecificTest::new); } - void check() { - checkCount.incrementAndGet(); + LambdaReturnKind lambdaReturnKind; + RetTypeKind[] returnType = new RetTypeKind[2]; + ArgTypeKind[] argumentKind = new ArgTypeKind[2]; - if (ak1 != ak2) - return; + boolean hasSameArguments() { + return argumentKind[0] == argumentKind[1]; + } + + boolean hasCompatibleReturns() { + return lambdaReturnKind.compatibleWith(returnType[0]) && + lambdaReturnKind.compatibleWith(returnType[1]); + } - if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2)) - return; + boolean hasSameOverloadPhase() { + return lambdaReturnKind.needsConversion(returnType[0]) == lambdaReturnKind.needsConversion(returnType[1]); + } - if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2)) - return; + @Override + public void doWork() throws Throwable { + check(newCompilationTask() + .withSourceFromTemplate(sourceTemplate) + .withOption("-XDverboseResolution=all,-predef,-internal,-object-init") + .analyze()); + } - boolean m1MoreSpecific = rt1.moreSpecificThan(rt2); - boolean m2MoreSpecific = rt2.moreSpecificThan(rt1); + void check(Result> result) { + boolean m1MoreSpecific = returnType[0].moreSpecificThan(returnType[1]); + boolean m2MoreSpecific = returnType[1].moreSpecificThan(returnType[0]); boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); - if (ambiguous != diagChecker.ambiguityFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nAmbiguity found: " + diagChecker.ambiguityFound + + if (ambiguous != ambiguityFound(result)) { + fail("invalid diagnostics for combo:\n" + + result.compilationInfo() + "\n" + + "\nAmbiguity found: " + ambiguityFound(result) + "\nm1 more specific: " + m1MoreSpecific + "\nm2 more specific: " + m2MoreSpecific + "\nexpected ambiguity: " + ambiguous); @@ -263,44 +231,32 @@ if (!ambiguous) { String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)"; - if (!sigToCheck.equals(diagChecker.mostSpecificSig)) { - throw new Error("invalid most specific method selected:\n" + - source.getCharContent(true) + - "\nMost specific found: " + diagChecker.mostSpecificSig + - "\nm1 more specific: " + m1MoreSpecific + - "\nm2 more specific: " + m2MoreSpecific); + if (!sigToCheck.equals(mostSpecificSignature(result))) { + fail("invalid most specific method selected:\n" + + result.compilationInfo() + "\n" + + "\nMost specific found: " + mostSpecificSignature(result) + + "\nm1 more specific: " + m1MoreSpecific + + "\nm2 more specific: " + m2MoreSpecific); } } } - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean ambiguityFound; - String mostSpecificSig; + boolean ambiguityFound(Result> result) { + return result.containsKey("compiler.err.ref.ambiguous"); + } - public void report(Diagnostic diagnostic) { - try { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR && - diagnostic.getCode().equals("compiler.err.ref.ambiguous")) { - ambiguityFound = true; - } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE && - diagnostic.getCode() - .equals("compiler.note.verbose.resolve.multi")) { - ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = - (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic; - JCDiagnostic.MultilineDiagnostic mdiag = - (JCDiagnostic.MultilineDiagnostic)dsu.d; - int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; - mostSpecificSig = - ((JCDiagnostic)mdiag.getSubdiagnostics() - .get(mostSpecificIndex)).getArgs()[1].toString(); - } - } catch (RuntimeException t) { - t.printStackTrace(); - throw t; - } + String mostSpecificSignature(Result> result) { + List> rsDiag = + result.diagnosticsForKey("compiler.note.verbose.resolve.multi"); + if (rsDiag.nonEmpty()) { + ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = + (ClientCodeWrapper.DiagnosticSourceUnwrapper)rsDiag.head; + JCDiagnostic.MultilineDiagnostic mdiag = + (JCDiagnostic.MultilineDiagnostic)dsu.d; + int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; + return mdiag.getSubdiagnostics().get(mostSpecificIndex).getArgs()[1].toString(); + } else { + return null; } } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java --- a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,31 +23,31 @@ /** * @test - * @bug 8003280 8006694 + * @bug 8003280 8006694 8129962 * @summary Add lambda tests * perform automated checks in type inference in lambda expressions * in different contexts * temporarily workaround combo tests are causing time out in several platforms - * @library ../../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper * @compile TypeInferenceComboTest.java - * @run main/othervm/timeout=360 TypeInferenceComboTest + * @run main TypeInferenceComboTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -public class TypeInferenceComboTest - extends JavacTestingAbstractThreadedTest - implements Runnable { +public class TypeInferenceComboTest extends ComboInstance { enum Context { ASSIGNMENT("SAM#Type s = #LBody;"), METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" + @@ -221,82 +221,21 @@ } } - boolean checkTypeInference() { - if (parameterType == TypeKind.VOID) { - if (lambdaBodyType != LambdaBody.RETURN_VOID) - return false; - } - else if (lambdaBodyType != LambdaBody.RETURN_ARG) - return false; - - return true; - } - - String templateStr = "#C\n" + - "interface SAM2 {\n" + - " SAM m();\n" + - "}\n"; - SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) { - public String toString() { - return template.replaceAll("#C", - samKind.getSam(parameterType, returnType)); - } - }; - - SourceFile clientSourceFile = new SourceFile("Client.java", - "class Client { \n" + - " #Context\n" + - "}") { - public String toString() { - return template.replaceAll("#Context", - context.getContext(samKind, samTargetType, keyword, - parameterType, returnType, lambdaKind, parameterKind, - genericDeclKind, lambdaBodyType)); - } - }; - - public void run() { - DiagnosticChecker dc = new DiagnosticChecker(); - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc, - null, null, Arrays.asList(samSourceFile, clientSourceFile)); - try { - ct.analyze(); - } catch (Throwable t) { - processException(t); - } - if (dc.errorFound == checkTypeInference()) { - throw new AssertionError(samSourceFile + "\n\n" + - clientSourceFile + "\n" + parameterType + " " + returnType); - } - } - - abstract class SourceFile extends SimpleJavaFileObject { - - protected String template; - - public SourceFile(String filename, String template) { - super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); - this.template = template; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return toString(); - } - - public abstract String toString(); - } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - boolean errorFound = false; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errorFound = true; - } - } + public static void main(String[] args) { + new ComboTestHelper() + .withFilter(TypeInferenceComboTest::badTestFilter) + .withFilter(TypeInferenceComboTest::redundantTestFilter) + .withDimension("SAM", (x, sam) -> x.samKind = sam, SamKind.values()) + .withDimension("SAMTARGET", (x, target) -> x.samTargetType = target, TypeKind.values()) + .withDimension("PARAMTYPE", (x, param) -> x.parameterType = param, TypeKind.values()) + .withDimension("RETTYPE", (x, ret) -> x.returnType = ret, TypeKind.values()) + .withDimension("CTX", (x, ctx) -> x.context = ctx, Context.values()) + .withDimension("LAMBDABODY", (x, body) -> x.lambdaBodyType = body, LambdaBody.values()) + .withDimension("LAMBDAKIND", (x, lambda) -> x.lambdaKind = lambda, LambdaKind.values()) + .withDimension("PARAMKIND", (x, param) -> x.parameterKind = param, ParameterKind.values()) + .withDimension("KEYWORD", (x, kw) -> x.keyword = kw, Keyword.values()) + .withDimension("GENDECL", (x, gk) -> x.genericDeclKind = gk, GenericDeclKind.values()) + .run(TypeInferenceComboTest::new); } SamKind samKind; @@ -310,84 +249,75 @@ Keyword keyword; GenericDeclKind genericDeclKind; - TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, - TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, - ParameterKind pk, Keyword kw, GenericDeclKind gdk) { - samKind = sk; - samTargetType = samTargetT; - parameterType = parameterT; - returnType = returnT; - context = c; - lambdaKind = lk; - parameterKind = pk; - keyword = kw; - lambdaBodyType = lb; - genericDeclKind = gdk; + boolean badTestFilter() { + if (samKind == SamKind.NON_GENERIC) { + return (parameterType != TypeKind.GENERIC && returnType != TypeKind.GENERIC); + } else { + return (samTargetType != TypeKind.VOID && + samTargetType != TypeKind.INT && + samTargetType != TypeKind.GENERIC && + (parameterType == TypeKind.GENERIC || + returnType == TypeKind.GENERIC)); + } } - public static void main(String[] args) throws Exception { - for(Context ct : Context.values()) { - for (TypeKind returnT : TypeKind.values()) { - for (TypeKind parameterT : TypeKind.values()) { - for(LambdaBody lb : LambdaBody.values()) { - for (ParameterKind parameterK : ParameterKind.values()) { - for(LambdaKind lambdaK : LambdaKind.values()) { - for (SamKind sk : SamKind.values()) { - if (sk == SamKind.NON_GENERIC) { - generateNonGenericSAM(ct, returnT, - parameterT, lb, parameterK, - lambdaK, sk); - } - else if (sk == SamKind.GENERIC) { - generateGenericSAM(ct, returnT, - parameterT, lb, parameterK, - lambdaK, sk); - } - } - } - } - } - } - } - } - - checkAfterExec(false); - } - - static void generateNonGenericSAM(Context ct, TypeKind returnT, - TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, - LambdaKind lambdaK, SamKind sk) { - if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) { - pool.execute(new TypeInferenceComboTest(sk, null, parameterT, - returnT, lb, ct, lambdaK, parameterK, null, null)); + boolean redundantTestFilter() { + if (samKind == SamKind.NON_GENERIC) { + return keyword.ordinal() == 0 && samTargetType.ordinal() == 0 && genericDeclKind.ordinal() == 0; + } else { + return context == Context.METHOD_CALL || genericDeclKind.ordinal() == 0; } } - static void generateGenericSAM(Context ct, TypeKind returnT, - TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, - LambdaKind lambdaK, SamKind sk) { - for (Keyword kw : Keyword.values()) { - for (TypeKind samTargetT : TypeKind.values()) { - if(samTargetT != TypeKind.VOID && - samTargetT != TypeKind.INT && - samTargetT != TypeKind.GENERIC && - (parameterT == TypeKind.GENERIC || - returnT == TypeKind.GENERIC)) { - if(ct != Context.METHOD_CALL) { - pool.execute( - new TypeInferenceComboTest(sk, samTargetT, parameterT, - returnT, lb, ct, lambdaK, parameterK, kw, null)); - } else {//Context.METHOD_CALL - for (GenericDeclKind gdk : - GenericDeclKind.values()) - pool.execute( - new TypeInferenceComboTest(sk, samTargetT, - parameterT, returnT, lb, ct, lambdaK, - parameterK, kw, gdk)); - } - } - } - } + String sam_template = "#{SAM}\n" + + "interface SAM2 {\n" + + " SAM m();\n" + + "}\n"; + + + String client_template = "class Client { \n" + + " #{CONTEXT}\n" + + "}"; + + @Override + public void doWork() throws IOException { + Result res = newCompilationTask() + .withSourceFromTemplate("Sam", sam_template, this::samClass) + .withSourceFromTemplate("Client", client_template, this::clientContext) + .analyze(); + + if (res.hasErrors() == checkTypeInference()) { + fail("Unexpected compilation output when compiling instance: " + res.compilationInfo()); + } } + ComboParameter samClass(String parameterName) { + switch (parameterName) { + case "SAM": + return new ComboParameter.Constant<>(samKind.getSam(parameterType, returnType)); + default: + return null; + } + } + + ComboParameter clientContext(String parameterName) { + switch (parameterName) { + case "CONTEXT": + return new ComboParameter.Constant<>(context.getContext(samKind, samTargetType, + keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType)); + default: + return null; + } + } + + boolean checkTypeInference() { + if (parameterType == TypeKind.VOID) { + if (lambdaBodyType != LambdaBody.RETURN_VOID) + return false; + } + else if (lambdaBodyType != LambdaBody.RETURN_ARG) + return false; + + return true; + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java --- a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import javax.tools.JavaCompiler; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -/** - * An abstract superclass for threaded tests. - * - * This class will try to read a property named test.concurrency. - * The property can be provided by passing this option to jtreg: - * -javaoption:-Dtest.concurrency=# - * - * If the property is not set the class will use a heuristic to determine the - * maximum number of threads that can be fired to execute a given test. - * - * This code will have to be revisited if jprt starts using concurrency for - * for running jtreg tests. - */ -public abstract class JavacTestingAbstractThreadedTest { - - protected static AtomicInteger numberOfThreads = new AtomicInteger(); - - protected static int getThreadPoolSize() { - Integer testConc = Integer.getInteger("test.concurrency"); - if (testConc != null) return testConc; - int cores = Runtime.getRuntime().availableProcessors(); - numberOfThreads.set(Math.max(2, Math.min(8, cores / 2))); - return numberOfThreads.get(); - } - - protected static void checkAfterExec() throws InterruptedException { - checkAfterExec(true); - }; - - protected static boolean throwAssertionOnError = true; - - protected static boolean printAll = false; - - protected static StringWriter errSWriter = new StringWriter(); - protected static PrintWriter errWriter = new PrintWriter(errSWriter); - - protected static StringWriter outSWriter = new StringWriter(); - protected static PrintWriter outWriter = new PrintWriter(outSWriter); - - protected static void checkAfterExec(boolean printCheckCount) - throws InterruptedException { - pool.shutdown(); - pool.awaitTermination(15, TimeUnit.MINUTES); - if (errCount.get() > 0) { - if (throwAssertionOnError) { - closePrinters(); - System.err.println(errSWriter.toString()); - throw new AssertionError( - String.format("%d errors found", errCount.get())); - } else { - System.err.println( - String.format("%d errors found", errCount.get())); - } - } else if (printCheckCount) { - outWriter.println("Total check executed: " + checkCount.get()); - } - /* - * This output is for supporting debugging. It does not mean that a given - * test had executed that number of threads concurrently. The value printed - * here is the maximum possible amount. - */ - closePrinters(); - if (printAll) { - System.out.println(errSWriter.toString()); - System.out.println(outSWriter.toString()); - } - System.out.println("Total number of threads in thread pool: " + - numberOfThreads.get()); - } - - protected static void closePrinters() { - errWriter.close(); - outWriter.close(); - } - - protected static void processException(Throwable t) { - errCount.incrementAndGet(); - t.printStackTrace(errWriter); - pool.shutdown(); - } - - //number of checks executed - protected static AtomicInteger checkCount = new AtomicInteger(); - - //number of errors found while running combo tests - protected static AtomicInteger errCount = new AtomicInteger(); - - //create default shared JavaCompiler - reused across multiple compilations - protected static JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); - - protected static ExecutorService pool = Executors.newFixedThreadPool( - getThreadPoolSize(), new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - pool.shutdown(); - errCount.incrementAndGet(); - e.printStackTrace(System.err); - } - }); - return t; - } - }); - - /* - * File manager is not thread-safe so it cannot be re-used across multiple - * threads. However we cache per-thread FileManager to avoid excessive - * object creation - */ - protected static final ThreadLocal fm = - new ThreadLocal() { - @Override protected StandardJavaFileManager initialValue() { - return comp.getStandardFileManager(null, null, null); - } - }; - -} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/combo/ComboInstance.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/combo/ComboInstance.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package combo; + +import javax.tools.StandardJavaFileManager; +import java.util.Optional; + +/** + * This class is the common superclass of all combo test instances. It defines few helper methods + * to build compilation tasks using the shared context object, as well as entry points for + * signalling test failures. + */ +public abstract class ComboInstance> { + + /** The test instance result status. */ + private ResultStatus resultStatus = ResultStatus.PASSED; + + /** The test instance execution environment. */ + private ComboTestHelper.Env env; + + /** + * Entry point for executing a combo test instance; first, the test environment is saved + * in the corresponding field, then the instance is run (see {@link ComboInstance#doWork()}. + * During execution, the result status will be updated to match the test outcome. + */ + final void run(ComboTestHelper.Env env) { + try { + this.env = env; + doWork(); + if (resultStatus.isSuccess()) { + env.info().passCount++; + } + } catch (Throwable ex) { + resultStatus = ResultStatus.ERROR; + env.info().errCount++; + env.info().lastError = Optional.of(ex); + } finally { + this.env = null; + } + } + + /** + * Retrieve a unique ID associated with this test instance. + */ + public int id() { + return env.info().comboCount; + } + + /** + * Retrieve shared file manager. + */ + public StandardJavaFileManager fileManager() { + return env.fileManager(); + } + + /** + * Create a new compilation task using shared compilation context. + */ + protected ComboTask newCompilationTask() { + return new ComboTask(env); + } + + /** + * Main test execution entry point; subclasses must implement this method to define the test + * logic. + */ + protected abstract void doWork() throws Throwable; + + /** + * Report a test failure. + */ + protected void fail() { + //dump some default info (such as dimension bindings) + fail("Combo instance failed; " + env.bindings); + } + + /** + * Report a test failure with corresponding failure message. + */ + protected void fail(String msg) { + resultStatus = ResultStatus.FAILED; + env.info().failCount++; + env.info().lastFailure = Optional.of(msg); + } + + /** + * The status associated with this test instance execution. + */ + enum ResultStatus { + /** Test passed. */ + PASSED(true), + /** Test failed. */ + FAILED(false), + /** Test thrown unexpected error/exception. */ + ERROR(false); + + boolean success; + + ResultStatus(boolean success) { + this.success = success; + } + + boolean isSuccess() { + return success; + } + } +} \ No newline at end of file diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/combo/ComboParameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/combo/ComboParameter.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package combo; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A combo parameter represents an 'hole' in a template that can be replaced with a given string. + * The schema of such holes is defined in {@link ComboParameter#pattern}; the main routine for + * replacing holes in a template scheme is {@link ComboParameter#expandTemplate(String, Resolver)}. + */ +public interface ComboParameter { + + /** + * A combo parameter can take the form: + *

+ * #{MAJOR} + * #{MAJOR.} + * #{MAJOR.MINOR} + *

+ * where MAJOR can be IDENTIFIER or IDENTIFIER[NUMERIC_INDEX] + * and MINOR can be an identifier. + */ + Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}"); + + /** + * Entry point for the customizable replacement logic. Subclasses must implement this method to + * specify how a given template hole should be expanded. An optional contextual argument is passed + * in as parameter, to make expansion more flexible. + */ + String expand(String optParameter); + + /** + * Helper class for defining 'constant' combo parameters - i.e. parameters that always expand + * as a given string value - regardless of the context. + */ + class Constant implements ComboParameter { + + D data; + + public Constant(D data) { + this.data = data; + } + + @Override + public String expand(String _unused) { + return String.valueOf(data); + } + } + + /** + * Helper interface used to lookup parameters given a parameter name. + */ + interface Resolver { + ComboParameter lookup(String name); + } + + /** + * Main routine for replacing holes in a template string. Holes are repeatedly searches, their + * corresponding parameters retrieved, and replaced through expansion; since an expansion can + * lead to more holes, the process has to be applied until a fixed point is reached. + */ + static String expandTemplate(String template, Resolver resolver) { + CharSequence in = template; + StringBuffer out = new StringBuffer(); + while (true) { + boolean more = false; + Matcher m = pattern.matcher(in); + while (m.find()) { + String parameterName = m.group(1); + String minor = m.group(2); + ComboParameter parameter = resolver.lookup(parameterName); + if (parameter == null) { + throw new IllegalStateException("Unhandled parameter name " + parameterName); + } + + String replacement = parameter.expand(minor); + more |= pattern.matcher(replacement).find(); + m.appendReplacement(out, replacement); + } + m.appendTail(out); + if (!more) + return out.toString(); + else { + in = out; + out = new StringBuffer(); + } + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/combo/ComboTask.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/combo/ComboTask.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package combo; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.List; +import combo.ComboParameter.Resolver; + +import javax.lang.model.element.Element; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import java.io.IOException; +import java.io.Writer; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * This class represents a compilation task associated with a combo test instance. This is a small + * wrapper around {@link JavacTask} which allows for fluent setup style and which makes use of + * the shared compilation context to speedup performances. + */ +public class ComboTask { + + /** Sources to be compiled in this task. */ + private List sources = List.nil(); + + /** Options associated with this task. */ + private List options = List.nil(); + + /** Diagnostic collector. */ + private DiagnosticCollector diagsCollector = new DiagnosticCollector(); + + /** Output writer. */ + private Writer out; + + /** Listeners associated with this task. */ + private List listeners = List.nil(); + + /** Underlying javac task object. */ + private JavacTask task; + + /** Combo execution environment. */ + private ComboTestHelper.Env env; + + ComboTask(ComboTestHelper.Env env) { + this.env = env; + } + + /** + * Add a new source to this task. + */ + public ComboTask withSource(JavaFileObject comboSource) { + sources = sources.prepend(comboSource); + return this; + } + + /** + * Add a new template source with given name to this task; the template is replaced with + * corresponding combo parameters (as defined in the combo test environment). + */ + public ComboTask withSourceFromTemplate(String name, String template) { + return withSource(new ComboTemplateSource(name, template)); + } + + /** + * Add a new template source with default name ("Test") to this task; the template is replaced with + * corresponding combo parameters (as defined in the combo test environment). + */ + public ComboTask withSourceFromTemplate(String template) { + return withSource(new ComboTemplateSource("Test", template)); + } + + /** + * Add a new template source with given name to this task; the template is replaced with + * corresponding combo parameters (as defined in the combo test environment). A custom resolver + * is used to add combo parameter mappings to the current combo test environment. + */ + public ComboTask withSourceFromTemplate(String name, String template, Resolver resolver) { + return withSource(new ComboTemplateSource(name, template, resolver)); + } + + /** + * Add a new template source with default name ("Test") to this task; the template is replaced with + * corresponding combo parameters (as defined in the combo test environment). A custom resolver + * is used to add combo parameter mappings to the current combo test environment. + */ + public ComboTask withSourceFromTemplate(String template, Resolver resolver) { + return withSource(new ComboTemplateSource("Test", template, resolver)); + } + + /** + * Add a new option to this task. + */ + public ComboTask withOption(String opt) { + options = options.append(opt); + return this; + } + + /** + * Add a set of options to this task. + */ + public ComboTask withOptions(String[] opts) { + for (String opt : opts) { + options = options.append(opt); + } + return this; + } + + /** + * Add a set of options to this task. + */ + public ComboTask withOptions(Iterable opts) { + for (String opt : opts) { + options = options.append(opt); + } + return this; + } + + /** + * Set the output writer associated with this task. + */ + public ComboTask withWriter(Writer out) { + this.out = out; + return this; + } + + /** + * Add a task listener to this task. + */ + public ComboTask withListener(TaskListener listener) { + listeners = listeners.prepend(listener); + return this; + } + + /** + * Parse the sources associated with this task. + */ + public Result> parse() throws IOException { + return new Result<>(getTask().parse()); + } + + /** + * Parse and analyzes the sources associated with this task. + */ + public Result> analyze() throws IOException { + return new Result<>(getTask().analyze()); + } + + /** + * Parse, analyze and perform code generation for the sources associated with this task. + */ + public Result> generate() throws IOException { + return new Result<>(getTask().generate()); + } + + /** + * Fork a new compilation task; if possible the compilation context from previous executions is + * retained (see comments in ReusableContext as to when it's safe to do so); otherwise a brand + * new context is created. + */ + public JavacTask getTask() { + if (task == null) { + ReusableContext context = env.context(); + String opts = options == null ? "" : + StreamSupport.stream(options.spliterator(), false).collect(Collectors.joining()); + context.clear(); + if (!context.polluted && (context.opts == null || context.opts.equals(opts))) { + //we can reuse former context + env.info().ctxReusedCount++; + } else { + env.info().ctxDroppedCount++; + //it's not safe to reuse context - create a new one + context = env.setContext(new ReusableContext()); + } + context.opts = opts; + JavacTask javacTask = ((JavacTool)env.javaCompiler()).getTask(out, env.fileManager(), + diagsCollector, options, null, sources, context); + javacTask.setTaskListener(context); + for (TaskListener l : listeners) { + javacTask.addTaskListener(l); + } + task = javacTask; + } + return task; + } + + /** + * This class is used to help clients accessing the results of a given compilation task. + * Contains several helper methods to inspect diagnostics generated during the task execution. + */ + public class Result { + + /** The underlying compilation results. */ + private final D data; + + public Result(D data) { + this.data = data; + } + + public D get() { + return data; + } + + /** + * Did this task generate any error diagnostics? + */ + public boolean hasErrors() { + return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.ERROR); + } + + /** + * Did this task generate any warning diagnostics? + */ + public boolean hasWarnings() { + return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.WARNING); + } + + /** + * Did this task generate any note diagnostics? + */ + public boolean hasNotes() { + return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.NOTE); + } + + /** + * Did this task generate any diagnostic with given key? + */ + public boolean containsKey(String key) { + return diagsCollector.diagsByKeys.containsKey(key); + } + + /** + * Retrieve the list of diagnostics of a given kind. + */ + public List> diagnosticsForKind(Diagnostic.Kind kind) { + List> diags = diagsCollector.diagsByKind.get(kind); + return diags != null ? diags : List.nil(); + } + + /** + * Retrieve the list of diagnostics with given key. + */ + public List> diagnosticsForKey(String key) { + List> diags = diagsCollector.diagsByKeys.get(key); + return diags != null ? diags : List.nil(); + } + + /** + * Dump useful info associated with this task. + */ + public String compilationInfo() { + return "instance#" + env.info().comboCount + ":[ options = " + options + + ", diagnostics = " + diagsCollector.diagsByKeys.keySet() + + ", dimensions = " + env.bindings + + ", sources = \n" + sources.stream().map(s -> { + try { + return s.getCharContent(true); + } catch (IOException ex) { + return ""; + } + }).collect(Collectors.joining(",")) + "]"; + } + } + + /** + * This class represents a Java source file whose contents are defined in terms of a template + * string. The holes in such template are expanded using corresponding combo parameter + * instances which can be retrieved using a resolver object. + */ + class ComboTemplateSource extends SimpleJavaFileObject { + + String source; + Map localParametersCache = new HashMap<>(); + + protected ComboTemplateSource(String name, String template) { + this(name, template, null); + } + + protected ComboTemplateSource(String name, String template, Resolver resolver) { + super(URI.create("myfo:/" + env.info().comboCount + "/" + name + ".java"), Kind.SOURCE); + source = ComboParameter.expandTemplate(template, pname -> resolveParameter(pname, resolver)); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + + /** + * Combo parameter resolver function. First parameters are looked up in the global environment, + * then the local environment is looked up as a fallback. + */ + ComboParameter resolveParameter(String pname, Resolver resolver) { + //first search the env + ComboParameter parameter = env.parametersCache.get(pname); + if (parameter == null) { + //then lookup local cache + parameter = localParametersCache.get(pname); + if (parameter == null && resolver != null) { + //if still null and we have a custom resolution function, try that + parameter = resolver.lookup(pname); + if (parameter != null) { + //if a match was found, store it in the local cache to aviod redundant recomputation + localParametersCache.put(pname, parameter); + } + } + } + return parameter; + } + } + + /** + * Helper class to collect all diagnostic generated during the execution of a given compilation task. + */ + class DiagnosticCollector implements DiagnosticListener { + + Map>> diagsByKind = new HashMap<>(); + Map>> diagsByKeys = new HashMap<>(); + + public void report(Diagnostic diagnostic) { + List> diags = + diagsByKeys.getOrDefault(diagnostic.getCode(), List.nil()); + diagsByKeys.put(diagnostic.getCode(), diags.prepend(diagnostic)); + Diagnostic.Kind kind = diagnostic.getKind(); + diags = diagsByKind.getOrDefault(kind, List.nil()); + diagsByKind.put(kind, diags.prepend(diagnostic)); + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/combo/ComboTestHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/combo/ComboTestHelper.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package combo; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Stack; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + + +/** + * An helper class for defining combinatorial (aka "combo" tests). A combo test is made up of one + * or more 'dimensions' - each of which represent a different axis of the test space. For instance, + * if we wanted to test class/interface declaration, one dimension could be the keyword used for + * the declaration (i.e. 'class' vs. 'interface') while another dimension could be the class/interface + * modifiers (i.e. 'public', 'pachake-private' etc.). A combo test consists in running a test instance + * for each point in the test space; that is, for any combination of the combo test dimension: + *

+ * 'public' 'class' + * 'public' interface' + * 'package-private' 'class' + * 'package-private' 'interface' + * ... + *

+ * A new test instance {@link ComboInstance} is created, and executed, after its dimensions have been + * initialized accordingly. Each instance can either pass, fail or throw an unexpected error; this helper + * class defines several policies for how failures should be handled during a combo test execution + * (i.e. should errors be ignored? Do we want the first failure to result in a failure of the whole + * combo test?). + *

+ * Additionally, this helper class allows to specify filter methods that can be used to throw out + * illegal combinations of dimensions - for instance, in the example above, we might want to exclude + * all combinations involving 'protected' and 'private' modifiers, which are disallowed for toplevel + * declarations. + *

+ * While combo tests can be used for a variety of workloads, typically their main task will consist + * in performing some kind of javac compilation. For this purpose, this framework defines an optimized + * javac context {@link ReusableContext} which can be shared across multiple combo instances, + * when the framework detects it's safe to do so. This allows to reduce the overhead associated with + * compiler initialization when the test space is big. + */ +public class ComboTestHelper> { + + /** Failure mode. */ + FailMode failMode = FailMode.FAIL_FAST; + + /** Ignore mode. */ + IgnoreMode ignoreMode = IgnoreMode.IGNORE_NONE; + + /** Combo test instance filter. */ + Optional> optFilter = Optional.empty(); + + /** Combo test dimensions. */ + List> dimensionInfos = new ArrayList<>(); + + /** Combo test stats. */ + Info info = new Info(); + + /** Shared JavaCompiler used across all combo test instances. */ + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + + /** Shared file manager used across all combo test instances. */ + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + /** Shared context used across all combo instances. */ + ReusableContext context = new ReusableContext(); + + /** + * Set failure mode for this combo test. + */ + public ComboTestHelper withFailMode(FailMode failMode) { + this.failMode = failMode; + return this; + } + + /** + * Set ignore mode for this combo test. + */ + public ComboTestHelper withIgnoreMode(IgnoreMode ignoreMode) { + this.ignoreMode = ignoreMode; + return this; + } + + /** + * Set a filter for combo test instances to be ignored. + */ + public ComboTestHelper withFilter(Predicate filter) { + optFilter = Optional.of(optFilter.map(filter::and).orElse(filter)); + return this; + } + + /** + * Adds a new dimension to this combo test, with a given name an array of values. + */ + @SafeVarargs + public final ComboTestHelper withDimension(String name, D... dims) { + return withDimension(name, null, dims); + } + + /** + * Adds a new dimension to this combo test, with a given name, an array of values and a + * coresponding setter to be called in order to set the dimension value on the combo test instance + * (before test execution). + */ + @SuppressWarnings("unchecked") + @SafeVarargs + public final ComboTestHelper withDimension(String name, DimensionSetter setter, D... dims) { + dimensionInfos.add(new DimensionInfo<>(name, dims, setter)); + return this; + } + + /** + * Adds a new array dimension to this combo test, with a given base name. This allows to specify + * multiple dimensions at once; the names of the underlying dimensions will be generated from the + * base name, using standard array bracket notation - i.e. "DIM[0]", "DIM[1]", etc. + */ + @SafeVarargs + public final ComboTestHelper withArrayDimension(String name, int size, D... dims) { + return withArrayDimension(name, null, size, dims); + } + + /** + * Adds a new array dimension to this combo test, with a given base name, an array of values and a + * coresponding array setter to be called in order to set the dimension value on the combo test + * instance (before test execution). This allows to specify multiple dimensions at once; the names + * of the underlying dimensions will be generated from the base name, using standard array bracket + * notation - i.e. "DIM[0]", "DIM[1]", etc. + */ + @SafeVarargs + public final ComboTestHelper withArrayDimension(String name, ArrayDimensionSetter setter, int size, D... dims) { + for (int i = 0 ; i < size ; i++) { + dimensionInfos.add(new ArrayDimensionInfo<>(name, dims, i, setter)); + } + return this; + } + + /** + * Returns the stat object associated with this combo test. + */ + public Info info() { + return info; + } + + /** + * Runs this combo test. This will generate the combinatorial explosion of all dimensions, and + * execute a new test instance (built using given supplier) for each such combination. + */ + public void run(Supplier instanceBuilder) { + run(instanceBuilder, null); + } + + /** + * Runs this combo test. This will generate the combinatorial explosion of all dimensions, and + * execute a new test instance (built using given supplier) for each such combination. Before + * executing the test instance entry point, the supplied initialization method is called on + * the test instance; this is useful for ad-hoc test instance initialization once all the dimension + * values have been set. + */ + public void run(Supplier instanceBuilder, Consumer initAction) { + runInternal(0, new Stack<>(), instanceBuilder, Optional.ofNullable(initAction)); + end(); + } + + /** + * Generate combinatorial explosion of all dimension values and create a new test instance + * for each combination. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private void runInternal(int index, Stack> bindings, Supplier instanceBuilder, Optional> initAction) { + if (index == dimensionInfos.size()) { + runCombo(instanceBuilder, initAction, bindings); + } else { + DimensionInfo dinfo = dimensionInfos.get(index); + for (Object d : dinfo.dims) { + bindings.push(new DimensionBinding(d, dinfo)); + runInternal(index + 1, bindings, instanceBuilder, initAction); + bindings.pop(); + } + } + } + + /** + * Run a new test instance using supplied dimension bindings. All required setters and initialization + * method are executed before calling the instance main entry point. Also checks if the instance + * is compatible with the specified test filters; if not, the test is simply skipped. + */ + @SuppressWarnings("unchecked") + private void runCombo(Supplier instanceBuilder, Optional> initAction, List> bindings) { + X x = instanceBuilder.get(); + for (DimensionBinding binding : bindings) { + binding.init(x); + } + initAction.ifPresent(action -> action.accept(x)); + info.comboCount++; + if (!optFilter.isPresent() || optFilter.get().test(x)) { + x.run(new Env(bindings)); + if (failMode.shouldStop(ignoreMode, info)) { + end(); + } + } else { + info.skippedCount++; + } + } + + /** + * This method is executed upon combo test completion (either normal or erroneous). Closes down + * all pending resources and dumps useful stats info. + */ + private void end() { + try { + fm.close(); + if (info.hasFailures()) { + throw new AssertionError("Failure when executing combo:" + info.lastFailure.orElse("")); + } else if (info.hasErrors()) { + throw new AssertionError("Unexpected exception while executing combo", info.lastError.get()); + } + } catch (IOException ex) { + throw new AssertionError("Failure when closing down shared file manager; ", ex); + } finally { + info.dump(); + } + } + + /** + * Functional interface for specifying combo test instance setters. + */ + public interface DimensionSetter, D> { + void set(X x, D d); + } + + /** + * Functional interface for specifying combo test instance array setters. The setter method + * receives an extra argument for the index of the array element to be set. + */ + public interface ArrayDimensionSetter, D> { + void set(X x, D d, int index); + } + + /** + * Dimension descriptor; each dimension has a name, an array of value and an optional setter + * to be called on the associated combo test instance. + */ + class DimensionInfo { + String name; + D[] dims; + boolean isParameter; + Optional> optSetter; + + DimensionInfo(String name, D[] dims, DimensionSetter setter) { + this.name = name; + this.dims = dims; + this.optSetter = Optional.ofNullable(setter); + this.isParameter = dims[0] instanceof ComboParameter; + } + } + + /** + * Array dimension descriptor. The dimension name is derived from a base name and an index using + * standard bracket notation; ; the setter accepts an additional 'index' argument to point + * to the array element to be initialized. + */ + class ArrayDimensionInfo extends DimensionInfo { + public ArrayDimensionInfo(String name, D[] dims, int index, ArrayDimensionSetter setter) { + super(String.format("%s[%d]", name, index), dims, + setter != null ? (x, d) -> setter.set(x, d, index) : null); + } + } + + /** + * Failure policies for a combo test run. + */ + public enum FailMode { + /** Combo test fails when first failure is detected. */ + FAIL_FAST, + /** Combo test fails after all instances have been executed. */ + FAIL_AFTER; + + boolean shouldStop(IgnoreMode ignoreMode, Info info) { + switch (this) { + case FAIL_FAST: + return !ignoreMode.canIgnore(info); + default: + return false; + } + } + } + + /** + * Ignore policies for a combo test run. + */ + public enum IgnoreMode { + /** No error or failure is ignored. */ + IGNORE_NONE, + /** Only errors are ignored. */ + IGNORE_ERRORS, + /** Only failures are ignored. */ + IGNORE_FAILURES, + /** Both errors and failures are ignored. */ + IGNORE_ALL; + + boolean canIgnore(Info info) { + switch (this) { + case IGNORE_ERRORS: + return info.failCount == 0; + case IGNORE_FAILURES: + return info.errCount == 0; + case IGNORE_ALL: + return true; + default: + return info.failCount == 0 && info.errCount == 0; + } + } + } + + /** + * A dimension binding. This is essentially a pair of a dimension value and its corresponding + * dimension info. + */ + class DimensionBinding { + D d; + DimensionInfo info; + + DimensionBinding(D d, DimensionInfo info) { + this.d = d; + this.info = info; + } + + void init(X x) { + info.optSetter.ifPresent(setter -> setter.set(x, d)); + } + + public String toString() { + return String.format("(%s -> %s)", info.name, d); + } + } + + /** + * This class is used to keep track of combo tests stats; info such as numbero of failures/errors, + * number of times a context has been shared/dropped are all recorder here. + */ + public static class Info { + int failCount; + int errCount; + int passCount; + int comboCount; + int skippedCount; + int ctxReusedCount; + int ctxDroppedCount; + Optional lastFailure = Optional.empty(); + Optional lastError = Optional.empty(); + + void dump() { + System.err.println(String.format("%d total checks executed", comboCount)); + System.err.println(String.format("%d successes found", passCount)); + System.err.println(String.format("%d failures found", failCount)); + System.err.println(String.format("%d errors found", errCount)); + System.err.println(String.format("%d skips found", skippedCount)); + System.err.println(String.format("%d contexts shared", ctxReusedCount)); + System.err.println(String.format("%d contexts dropped", ctxDroppedCount)); + } + + public boolean hasFailures() { + return failCount != 0; + } + + public boolean hasErrors() { + return errCount != 0; + } + } + + /** + * THe execution environment for a given combo test instance. An environment contains the + * bindings for all the dimensions, along with the combo parameter cache (this is non-empty + * only if one or more dimensions are subclasses of the {@code ComboParameter} interface). + */ + class Env { + List> bindings; + Map parametersCache = new HashMap<>(); + + @SuppressWarnings({"Unchecked", "rawtypes"}) + Env(List> bindings) { + this.bindings = bindings; + for (DimensionBinding binding : bindings) { + if (binding.info.isParameter) { + parametersCache.put(binding.info.name, (ComboParameter)binding.d); + }; + } + } + + Info info() { + return ComboTestHelper.this.info(); + } + + StandardJavaFileManager fileManager() { + return fm; + } + + JavaCompiler javaCompiler() { + return comp; + } + + ReusableContext context() { + return context; + } + + ReusableContext setContext(ReusableContext context) { + return ComboTestHelper.this.context = context; + } + } +} + + + diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/lib/combo/ReusableContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lib/combo/ReusableContext.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package combo; + +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.api.MultiTaskListener; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.comp.Check; +import com.sun.tools.javac.comp.CompileStates; +import com.sun.tools.javac.comp.Enter; +import com.sun.tools.javac.main.Arguments; +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import java.util.HashSet; +import java.util.Set; + +/** + * A reusable context is a context that can be used safely across multiple compilation rounds + * arising from execution of a combo test. It achieves reuse by replacing some components + * (most notably JavaCompiler and Log) with reusable counterparts, and by exposing a method + * to cleanup leftovers from previous compilation. + *

+ * There are, however, situations in which reusing the context is not safe: (i) when different + * compilations are using different sets of compiler options (as most option values are cached + * inside components themselves) and (ii) when the compilation unit happens to redefine classes + * in the java.* packages. + */ +class ReusableContext extends Context implements TaskListener { + + Set roots = new HashSet<>(); + + String opts; + boolean polluted = false; + + ReusableContext() { + super(); + put(Log.logKey, ReusableLog.factory); + put(JavaCompiler.compilerKey, ReusableJavaCompiler.factory); + } + + void clear() { + drop(Arguments.argsKey); + drop(DiagnosticListener.class); + drop(Log.outKey); + drop(JavaFileManager.class); + drop(JavacTask.class); + + if (ht.get(Log.logKey) instanceof ReusableLog) { + //log already inited - not first round + ((ReusableLog)Log.instance(this)).clear(); + Enter.instance(this).newRound(); + ((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear(); + Types.instance(this).newRound(); + Check.instance(this).newRound(); + CompileStates.instance(this).clear(); + MultiTaskListener.instance(this).clear(); + + //find if any of the roots have redefined java.* classes + Symtab syms = Symtab.instance(this); + new TreeScanner() { + @Override + public Void visitClass(ClassTree node, Void aVoid) { + Symbol sym = ((JCClassDecl)node).sym; + if (sym != null) { + syms.classes.remove(sym.flatName()); + if (sym.flatName().toString().startsWith("java.")) { + polluted = true; + } + } + return super.visitClass(node, aVoid); + } + }.scan(roots, null); + roots.clear(); + } + } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() == Kind.PARSE) { + roots.add(e.getCompilationUnit()); + } + } + + @Override + public void started(TaskEvent e) { + //do nothing + } + + void drop(Key k) { + ht.remove(k); + } + + void drop(Class c) { + ht.remove(key(c)); + } + + /** + * Reusable JavaCompiler; exposes a method to clean up the component from leftovers associated with + * previous compilations. + */ + static class ReusableJavaCompiler extends JavaCompiler { + + static Factory factory = ReusableJavaCompiler::new; + + ReusableJavaCompiler(Context context) { + super(context); + } + + @Override + public void close() { + //do nothing + } + + void clear() { + newRound(); + } + + @Override + protected void checkReusable() { + //do nothing - it's ok to reuse the compiler + } + } + + /** + * Reusable Log; exposes a method to clean up the component from leftovers associated with + * previous compilations. + */ + static class ReusableLog extends Log { + + static Factory factory = ReusableLog::new; + + Context context; + + ReusableLog(Context context) { + super(context); + this.context = context; + } + + void clear() { + recorded.clear(); + sourceMap.clear(); + nerrors = 0; + nwarnings = 0; + //Set a fake listener that will lazily lookup the context for the 'real' listener. Since + //this field is never updated when a new task is created, we cannot simply reset the field + //or keep old value. This is a hack to workaround the limitations in the current infrastructure. + diagListener = new DiagnosticListener() { + DiagnosticListener cachedListener; + + @Override + @SuppressWarnings("unchecked") + public void report(Diagnostic diagnostic) { + if (cachedListener == null) { + cachedListener = context.get(DiagnosticListener.class); + } + cachedListener.report(diagnostic); + } + }; + } + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java --- a/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,30 +23,31 @@ /* * @test - * @bug 7030606 8006694 + * @bug 7030606 8006694 8129962 * @summary Project-coin: multi-catch types should be pairwise disjoint * temporarily workaround combo tests are causing time out in several platforms - * @library ../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm DisjunctiveTypeWellFormednessTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main DisjunctiveTypeWellFormednessTest */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import com.sun.source.util.JavacTask; +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; -public class DisjunctiveTypeWellFormednessTest - extends JavacTestingAbstractThreadedTest - implements Runnable { - enum Alternative { +public class DisjunctiveTypeWellFormednessTest extends ComboInstance { + + enum Alternative implements ComboParameter { EXCEPTION("Exception"), RUNTIME_EXCEPTION("RuntimeException"), IO_EXCEPTION("java.io.IOException"), @@ -55,21 +56,10 @@ String exceptionStr; - private Alternative(String exceptionStr) { + Alternative(String exceptionStr) { this.exceptionStr = exceptionStr; } - static String makeDisjunctiveType(Alternative... alternatives) { - StringBuilder buf = new StringBuilder(); - String sep = ""; - for (Alternative alternative : alternatives) { - buf.append(sep); - buf.append(alternative.exceptionStr); - sep = "|"; - } - return buf.toString(); - } - boolean disjoint(Alternative that) { return disjoint[this.ordinal()][that.ordinal()]; } @@ -82,135 +72,85 @@ /*FileNotFoundException*/ { false, true, false, false, true }, /*IllegalArgumentException*/ { false, false, true, true, false } }; + + @Override + public String expand(String optParameter) { + return exceptionStr; + } } - enum Arity { - ONE(1), - TWO(2), - THREE(3), - FOUR(4), - FIVE(5); + enum Arity implements ComboParameter { + ONE(1, "#{TYPE[0]}"), + TWO(2, "#{TYPE[0]} | #{TYPE[1]}"), + THREE(3, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]}"), + FOUR(4, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]} | #{TYPE[3]}"), + FIVE(5, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]} | #{TYPE[3]} | #{TYPE[4]}"); int n; + String arityTemplate; - private Arity(int n) { + Arity(int n, String arityTemplate) { this.n = n; + this.arityTemplate = arityTemplate; + } + + @Override + public String expand(String optParameter) { + return arityTemplate; } } public static void main(String... args) throws Exception { - for (Arity arity : Arity.values()) { - for (Alternative a1 : Alternative.values()) { - if (arity == Arity.ONE) { - pool.execute(new DisjunctiveTypeWellFormednessTest(a1)); - continue; - } - for (Alternative a2 : Alternative.values()) { - if (arity == Arity.TWO) { - pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2)); - continue; - } - for (Alternative a3 : Alternative.values()) { - if (arity == Arity.THREE) { - pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3)); - continue; - } - for (Alternative a4 : Alternative.values()) { - if (arity == Arity.FOUR) { - pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4)); - continue; - } - for (Alternative a5 : Alternative.values()) { - pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5)); - } - } - } + new ComboTestHelper() + .withFilter(DisjunctiveTypeWellFormednessTest::arityFilter) + .withDimension("CTYPE", (x, arity) -> x.arity = arity, Arity.values()) + .withArrayDimension("TYPE", (x, type, idx) -> x.alternatives[idx] = type, 5, Alternative.values()) + .run(DisjunctiveTypeWellFormednessTest::new); + } + + Arity arity; + Alternative[] alternatives = new Alternative[5]; + + boolean arityFilter() { + for (int i = arity.n; i < alternatives.length ; i++) { + if (alternatives[i].ordinal() != 0) { + return false; + } + } + return true; + } + + String template = "class Test {\n" + + "void test() {\n" + + "try {} catch (#{CTYPE} e) {}\n" + + "}\n" + + "}\n"; + + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(template) + .analyze()); + } + + void check(Result res) { + + int non_disjoint = 0; + for (int i = 0 ; i < arity.n ; i++) { + for (int j = 0 ; j < i ; j++) { + if (!alternatives[i].disjoint(alternatives[j])) { + non_disjoint++; + break; } } } - checkAfterExec(false); - } - - Alternative[] alternatives; - JavaSource source; - DiagnosticChecker diagChecker; - - DisjunctiveTypeWellFormednessTest(Alternative... alternatives) { - this.alternatives = alternatives; - this.source = new JavaSource(); - this.diagChecker = new DiagnosticChecker(); - } - - class JavaSource extends SimpleJavaFileObject { - - String template = "class Test {\n" + - "void test() {\n" + - "try {} catch (#T e) {}\n" + - "}\n" + - "}\n"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replace("#T", Alternative.makeDisjunctiveType(alternatives)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + int foundErrs = res.diagnosticsForKey("compiler.err.multicatch.types.must.be.disjoint").size(); + if (non_disjoint != foundErrs) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nFound errors: " + foundErrs + + "\nExpected errors: " + non_disjoint); } } - - @Override - public void run() { - JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, - null, null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable t) { - processException(t); - return; - } - check(); - } - - void check() { - - int non_disjoint = 0; - int i = 0; - for (Alternative a1 : alternatives) { - int j = 0; - for (Alternative a2 : alternatives) { - if (i == j) continue; - if (!a1.disjoint(a2)) { - non_disjoint++; - break; - } - j++; - } - i++; - } - - if (non_disjoint != diagChecker.errorsFound) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nFound errors: " + diagChecker.errorsFound + - "\nExpected errors: " + non_disjoint); - } - } - - static class DiagnosticChecker implements javax.tools.DiagnosticListener { - - int errorsFound; - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR && - diagnostic.getCode().startsWith("compiler.err.multicatch.types.must.be.disjoint")) { - errorsFound++; - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/parser/8134007/T8134007.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/parser/8134007/T8134007.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8134007 + * @summary Improve string folding + * @compile T8134007.java + */ +class T8134007 { + String v = ""; + + //interleaved non-literals + String s1 = "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v; + + //heading non-literal + String s2 = v + "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"; + + //trailing non-literal + String s3 = "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v; +} diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/resolve/BitWiseOperators.java --- a/langtools/test/tools/javac/resolve/BitWiseOperators.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/resolve/BitWiseOperators.java Tue Sep 08 15:39:51 2015 -0700 @@ -21,47 +21,30 @@ * questions. */ -/**@test - * @bug 8082311 +/* + * @test + * @bug 8082311 8129962 * @summary Verify that bitwise operators don't allow to mix numeric and boolean operands. * @library ../lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main BitWiseOperators */ import com.sun.tools.javac.util.StringUtils; -import java.net.URI; -import java.util.Arrays; -import java.util.List; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -public class BitWiseOperators extends JavacTestingAbstractThreadedTest { - public static void main(String... args) { - new BitWiseOperators().run(); - } +import java.io.IOException; - void run() { - for (TYPE type1 : TYPE.values()) { - for (OPERATION op : OPERATION.values()) { - for (TYPE type2 : TYPE.values()) { - runTest(type1, op, type2); - } - } - } - } +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - void runTest(TYPE type1, OPERATION op, TYPE type2) { - DiagnosticCollector dc = new DiagnosticCollector<>(); - List files = Arrays.asList(new JavaSource(type1, op, type2)); - comp.getTask(null, null, dc, null, null, files).call(); - if (dc.getDiagnostics().isEmpty() ^ TYPE.compatible(type1, type2)) { - throw new AssertionError("Unexpected behavior. Type1: " + type1 + - "; type2: " + type2 + - "; diagnostics: " + dc.getDiagnostics()); - } - } - enum TYPE { +public class BitWiseOperators extends ComboInstance { + + enum OperandType implements ComboParameter { BYTE, CHAR, SHORT, @@ -69,45 +52,57 @@ LONG, BOOLEAN; - public static boolean compatible(TYPE op1, TYPE op2) { + public static boolean compatible(OperandType op1, OperandType op2) { return !(op1 == BOOLEAN ^ op2 == BOOLEAN); } + + @Override + public String expand(String optParameter) { + return StringUtils.toLowerCase(name()); + } } - enum OPERATION { + enum OperatorKind implements ComboParameter { BITAND("&"), BITOR("|"), BITXOR("^"); String op; - private OPERATION(String op) { + OperatorKind(String op) { this.op = op; } - } - - class JavaSource extends SimpleJavaFileObject { - - String template = "class Test {\n" + - " public Object test(#TYPE1 var1, #TYPE2 var2) {\n" + - " return var1 #OP var2;\n" + - " }\n" + - "}"; - - String source; - - public JavaSource(TYPE type1, OPERATION op, TYPE type2) { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replaceAll("#TYPE1", StringUtils.toLowerCase(type1.name())) - .replaceAll("#OP", StringUtils.toLowerCase(op.op)) - .replaceAll("#TYPE2", StringUtils.toLowerCase(type2.name())); - } - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + public String expand(String optParameter) { + return op; } } + public static void main(String... args) { + new ComboTestHelper() + .withArrayDimension("TYPE", (x, type, idx) -> x.opTypes[idx] = type, 2, OperandType.values()) + .withDimension("OP", OperatorKind.values()) + .run(BitWiseOperators::new); + } + + OperandType[] opTypes = new OperandType[2]; + + String template = "class Test {\n" + + " public Object test(#{TYPE[0]} var1, #{TYPE[1]} var2) {\n" + + " return var1 #{OP} var2;\n" + + " }\n" + + "}"; + + @Override + public void doWork() throws IOException { + Result res = newCompilationTask() + .withSourceFromTemplate(template) + .analyze(); + if (res.hasErrors() == OperandType.compatible(opTypes[0], opTypes[1])) { + fail("Unexpected behavior. Type1: " + opTypes[0] + + "; type2: " + opTypes[1] + + "; " + res.compilationInfo()); + } + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/types/ScopeListenerTest.java --- a/langtools/test/tools/javac/types/ScopeListenerTest.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/types/ScopeListenerTest.java Tue Sep 08 15:39:51 2015 -0700 @@ -29,6 +29,7 @@ */ import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Scope.ScopeListenerList; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Types; @@ -53,20 +54,14 @@ types.membersClosure(syms.stringType, true); types.membersClosure(syms.stringType, false); - Field listenersField = Scope.class.getDeclaredField("listeners"); - - listenersField.setAccessible(true); - - int listenerCount = - ((Collection) listenersField.get(syms.stringType.tsym.members())).size(); + int listenerCount = listenerCount(syms.stringType.tsym.members()); for (int i = 0; i < 100; i++) { types.membersClosure(syms.stringType, true); types.membersClosure(syms.stringType, false); } - int newListenerCount - = ((Collection) listenersField.get(syms.stringType.tsym.members())).size(); + int newListenerCount = listenerCount(syms.stringType.tsym.members()); if (listenerCount != newListenerCount) { throw new AssertionError("Orig listener count: " + listenerCount + @@ -79,4 +74,12 @@ ; } + int listenerCount(Scope s) throws ReflectiveOperationException { + Field listenersListField = Scope.class.getDeclaredField("listeners"); + listenersListField.setAccessible(true); + Field listenersField = ScopeListenerList.class.getDeclaredField("listeners"); + listenersField.setAccessible(true); + return ((Collection)listenersField.get(listenersListField.get(s))).size(); + } + } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/varargs/7042566/T7042566.java --- a/langtools/test/tools/javac/varargs/7042566/T7042566.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/varargs/7042566/T7042566.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,31 +23,25 @@ /* * @test - * @bug 7042566 8006694 + * @bug 7042566 8006694 8129962 * @summary Unambiguous varargs method calls flagged as ambiguous * temporarily workaround combo tests are causing time out in several platforms - * @library ../../lib + * @library /tools/javac/lib * @modules jdk.jdeps/com.sun.tools.classfile + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util - * @build JavacTestingAbstractThreadedTest - * @run main/othervm T7042566 + * @build combo.ComboTestHelper + * @run main T7042566 */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 +import java.io.IOException; +import java.io.InputStream; +import javax.tools.JavaFileObject; -import java.io.File; -import java.net.URI; -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicInteger; -import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; - -import com.sun.source.util.JavacTask; import com.sun.tools.classfile.Instruction; import com.sun.tools.classfile.Attribute; import com.sun.tools.classfile.ClassFile; @@ -56,145 +50,12 @@ import com.sun.tools.classfile.Method; import com.sun.tools.javac.util.List; -public class T7042566 - extends JavacTestingAbstractThreadedTest - implements Runnable { - - VarargsMethod m1; - VarargsMethod m2; - TypeConfiguration actuals; - - T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf, - TypeConfiguration actuals) { - this.m1 = new VarargsMethod(m1_conf); - this.m2 = new VarargsMethod(m2_conf); - this.actuals = actuals; - } - - @Override - public void run() { - int id = checkCount.incrementAndGet(); - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - JavaSource source = new JavaSource(id); - ErrorChecker ec = new ErrorChecker(); - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), ec, - null, null, Arrays.asList(source)); - ct.call(); - check(source, ec, id); - } - - void check(JavaSource source, ErrorChecker ec, int id) { - boolean resolutionError = false; - VarargsMethod selectedMethod = null; - - boolean m1_applicable = m1.isApplicable(actuals); - boolean m2_applicable = m2.isApplicable(actuals); - - if (!m1_applicable && !m2_applicable) { - resolutionError = true; - } else if (m1_applicable && m2_applicable) { - //most specific - boolean m1_moreSpecific = m1.isMoreSpecificThan(m2); - boolean m2_moreSpecific = m2.isMoreSpecificThan(m1); - - resolutionError = m1_moreSpecific == m2_moreSpecific; - selectedMethod = m1_moreSpecific ? m1 : m2; - } else { - selectedMethod = m1_applicable ? - m1 : m2; - } - - if (ec.errorFound != resolutionError) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nExpected resolution error: " + resolutionError + - "\nFound error: " + ec.errorFound + - "\nCompiler diagnostics:\n" + ec.printDiags()); - } else if (!resolutionError) { - verifyBytecode(selectedMethod, source, id); - } - } +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; - void verifyBytecode(VarargsMethod selected, JavaSource source, int id) { - bytecodeCheckCount.incrementAndGet(); - File compiledTest = new File(String.format("Test%d.class", id)); - try { - ClassFile cf = ClassFile.read(compiledTest); - Method testMethod = null; - for (Method m : cf.methods) { - if (m.getName(cf.constant_pool).equals("test")) { - testMethod = m; - break; - } - } - if (testMethod == null) { - throw new Error("Test method not found"); - } - Code_attribute ea = - (Code_attribute)testMethod.attributes.get(Attribute.Code); - if (testMethod == null) { - throw new Error("Code attribute for test() method not found"); - } - - for (Instruction i : ea.getInstructions()) { - if (i.getMnemonic().equals("invokevirtual")) { - int cp_entry = i.getUnsignedShort(1); - CONSTANT_Methodref_info methRef = - (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry); - String type = methRef.getNameAndTypeInfo().getType(); - String sig = selected.parameterTypes.bytecodeSigStr; - if (!type.contains(sig)) { - throw new Error("Unexpected type method call: " + - type + "" + - "\nfound: " + sig + - "\n" + source.getCharContent(true)); - } - break; - } - } - } catch (Exception e) { - e.printStackTrace(); - throw new Error("error reading " + compiledTest +": " + e); - } - } - - class JavaSource extends SimpleJavaFileObject { - - static final String source_template = "class Test#ID {\n" + - " #V1\n" + - " #V2\n" + - " void test() { m(#E); }\n" + - "}"; - - String source; - - public JavaSource(int id) { - super(URI.create(String.format("myfo:/Test%d.java", id)), - JavaFileObject.Kind.SOURCE); - source = source_template.replaceAll("#V1", m1.toString()) - .replaceAll("#V2", m2.toString()) - .replaceAll("#E", actuals.expressionListStr) - .replaceAll("#ID", String.valueOf(id)); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - public static void main(String... args) throws Exception { - for (TypeConfiguration tconf1 : TypeConfiguration.values()) { - for (TypeConfiguration tconf2 : TypeConfiguration.values()) { - for (TypeConfiguration tconf3 : TypeConfiguration.values()) { - pool.execute(new T7042566(tconf1, tconf2, tconf3)); - } - } - } - - outWriter.println("Bytecode checks made: " + bytecodeCheckCount.get()); - checkAfterExec(); - } +public class T7042566 extends ComboInstance { enum TypeKind { OBJECT("Object", "(Object)null", "Ljava/lang/Object;"), @@ -216,7 +77,7 @@ } } - enum TypeConfiguration { + enum TypeConfiguration implements ComboParameter { A(TypeKind.OBJECT), B(TypeKind.STRING), AA(TypeKind.OBJECT, TypeKind.OBJECT), @@ -237,7 +98,7 @@ String parameterListStr; String bytecodeSigStr; - private TypeConfiguration(TypeKind... typeKindList) { + TypeConfiguration(TypeKind... typeKindList) { this.typeKindList = List.from(typeKindList); expressionListStr = asExpressionList(); parameterListStr = asParameterList(); @@ -284,6 +145,11 @@ } return buf.toString(); } + + @Override + public String expand(String optParameter) { + return expressionListStr; + } } static class VarargsMethod { @@ -333,31 +199,119 @@ } } - static class ErrorChecker - implements javax.tools.DiagnosticListener { + public static void main(String[] args) { + new ComboTestHelper() + .withArrayDimension("SIG", (x, sig, idx) -> x.methodSignatures[idx] = sig, 2, TypeConfiguration.values()) + .withDimension("ACTUALS", (x, actuals) -> x.actuals = actuals, TypeConfiguration.values()) + .run(T7042566::new, T7042566::setup); + } - boolean errorFound; - List errDiags = List.nil(); + VarargsMethod m1; + VarargsMethod m2; + TypeConfiguration[] methodSignatures = new TypeConfiguration[2]; + TypeConfiguration actuals; + + void setup() { + this.m1 = new VarargsMethod(methodSignatures[0]); + this.m2 = new VarargsMethod(methodSignatures[1]); + } - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errDiags = errDiags - .append(diagnostic.getMessage(Locale.getDefault())); - errorFound = true; - } - } + final String source_template = "class Test {\n" + + " #{METH.1}\n" + + " #{METH.2}\n" + + " void test() { m(#{ACTUALS}); }\n" + + "}"; - String printDiags() { - StringBuilder buf = new StringBuilder(); - for (String s : errDiags) { - buf.append(s); - buf.append("\n"); - } - return buf.toString(); + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withSourceFromTemplate(source_template, this::getMethodDecl) + .generate()); + } + + ComboParameter getMethodDecl(String parameterName) { + switch (parameterName) { + case "METH": return optParameter -> { + return optParameter.equals("1") ? + m1.toString() : m2.toString(); + }; + default: + return null; } } - //number of bytecode checks made while running combo tests - static AtomicInteger bytecodeCheckCount = new AtomicInteger(); + void check(Result> res) { + boolean resolutionError = false; + VarargsMethod selectedMethod = null; + + boolean m1_applicable = m1.isApplicable(actuals); + boolean m2_applicable = m2.isApplicable(actuals); + + if (!m1_applicable && !m2_applicable) { + resolutionError = true; + } else if (m1_applicable && m2_applicable) { + //most specific + boolean m1_moreSpecific = m1.isMoreSpecificThan(m2); + boolean m2_moreSpecific = m2.isMoreSpecificThan(m1); + + resolutionError = m1_moreSpecific == m2_moreSpecific; + selectedMethod = m1_moreSpecific ? m1 : m2; + } else { + selectedMethod = m1_applicable ? + m1 : m2; + } + + if (res.hasErrors() != resolutionError) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + + "\nExpected resolution error: " + resolutionError + + "\nFound error: " + res.hasErrors()); + } else if (!resolutionError) { + verifyBytecode(res, selectedMethod); + } + } + void verifyBytecode(Result> res, VarargsMethod selected) { + try (InputStream is = res.get().iterator().next().openInputStream()) { + ClassFile cf = ClassFile.read(is); + Method testMethod = null; + for (Method m : cf.methods) { + if (m.getName(cf.constant_pool).equals("test")) { + testMethod = m; + break; + } + } + if (testMethod == null) { + fail("Test method not found"); + return; + } + Code_attribute ea = + (Code_attribute)testMethod.attributes.get(Attribute.Code); + if (testMethod == null) { + fail("Code attribute for test() method not found"); + return; + } + + for (Instruction i : ea.getInstructions()) { + if (i.getMnemonic().equals("invokevirtual")) { + int cp_entry = i.getUnsignedShort(1); + CONSTANT_Methodref_info methRef = + (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry); + String type = methRef.getNameAndTypeInfo().getType(); + String sig = selected.parameterTypes.bytecodeSigStr; + if (!type.contains(sig)) { + fail("Unexpected type method call: " + + type + "" + + "\nfound: " + sig + + "\n" + res.compilationInfo()); + return; + } + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + fail("error reading classfile; " + res.compilationInfo() +": " + e); + } + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/varargs/warning/Warn4.java --- a/langtools/test/tools/javac/varargs/warning/Warn4.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/varargs/warning/Warn4.java Tue Sep 08 15:39:51 2015 -0700 @@ -23,40 +23,39 @@ /** * @test - * @bug 6945418 6993978 8006694 7196160 + * @bug 6945418 6993978 8006694 7196160 8129962 * @summary Project Coin: Simplified Varargs Method Invocation * temporarily workaround combo tests are causing time out in several platforms - * @author mcimadamore - * @library ../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest - * @run main/othervm Warn4 + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + * @run main Warn4 */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import java.net.URI; -import java.util.Arrays; +import java.io.IOException; import java.util.Set; import java.util.HashSet; import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; +import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; -import com.sun.source.util.JavacTask; -public class Warn4 - extends JavacTestingAbstractThreadedTest - implements Runnable { +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + +public class Warn4 extends ComboInstance { final static Warning[] error = null; final static Warning[] none = new Warning[] {}; final static Warning[] vararg = new Warning[] { Warning.VARARGS }; final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED }; - final static Warning[] both = - new Warning[] { Warning.VARARGS, Warning.UNCHECKED }; + final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED }; enum Warning { UNCHECKED("generic.array.creation"), @@ -105,7 +104,7 @@ } } - enum TrustMe { + enum TrustMe implements ComboParameter { DONT_TRUST(""), TRUST("@java.lang.SafeVarargs"); @@ -114,9 +113,14 @@ TrustMe(String anno) { this.anno = anno; } + + @Override + public String expand(String optParameter) { + return anno; + } } - enum ModifierKind { + enum ModifierKind implements ComboParameter { NONE(" "), FINAL("final "), STATIC("static "), @@ -127,9 +131,14 @@ ModifierKind(String mod) { this.mod = mod; } + + @Override + public String expand(String optParameter) { + return mod; + } } - enum SuppressLevel { + enum SuppressLevel implements ComboParameter { NONE(""), UNCHECKED("unchecked"); @@ -139,21 +148,22 @@ this.lint = lint; } - String getSuppressAnno() { + @Override + public String expand(String optParameter) { return "@SuppressWarnings(\"" + lint + "\")"; } } - enum Signature { - UNBOUND("void #name(List#arity arg) { #body }", + enum Signature implements ComboParameter { + UNBOUND("void #NAME(List#ARITY arg) { #BODY }", new Warning[][] {none, none, none, none, error}), - INVARIANT_TVAR(" void #name(List#arity arg) { #body }", + INVARIANT_TVAR(" void #NAME(List#ARITY arg) { #BODY }", new Warning[][] {both, both, error, both, error}), - TVAR(" void #name(Z#arity arg) { #body }", + TVAR(" void #NAME(Z#ARITY arg) { #BODY }", new Warning[][] {both, both, both, both, vararg}), - INVARIANT("void #name(List#arity arg) { #body }", + INVARIANT("void #NAME(List#ARITY arg) { #BODY }", new Warning[][] {error, error, error, both, error}), - UNPARAMETERIZED("void #name(String#arity arg) { #body }", + UNPARAMETERIZED("void #NAME(String#ARITY arg) { #BODY }", new Warning[][] {error, error, error, error, none}); String template; @@ -177,130 +187,85 @@ return warnings[other.ordinal()] == vararg || warnings[other.ordinal()] == both; } + + @Override + public String expand(String optParameter) { + if (optParameter.equals("CLIENT")) { + return template.replaceAll("#ARITY", "") + .replaceAll("#NAME", "test") + .replaceAll("#BODY", "m(arg)"); + } else { + return template.replaceAll("#ARITY", "...") + .replaceAll("#NAME", "m") + .replaceAll("#BODY", ""); + } + } } - public static void main(String... args) throws Exception { - for (SourceLevel sourceLevel : SourceLevel.values()) { - for (TrustMe trustMe : TrustMe.values()) { - for (SuppressLevel suppressLevelClient : SuppressLevel.values()) { - for (SuppressLevel suppressLevelDecl : SuppressLevel.values()) { - for (ModifierKind modKind : ModifierKind.values()) { - for (Signature vararg_meth : Signature.values()) { - for (Signature client_meth : Signature.values()) { - if (vararg_meth.isApplicableTo(client_meth)) { - pool.execute(new Warn4(sourceLevel, - trustMe, - suppressLevelClient, - suppressLevelDecl, - modKind, - vararg_meth, - client_meth)); - } - } - } - } - } - } - } - } - - checkAfterExec(); + public static void main(String... args) { + new ComboTestHelper() + .withFilter(Warn4::badTestFilter) + .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values()) + .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values()) + .withArrayDimension("SUPPRESS", (x, suppress, idx) -> x.suppress[idx] = suppress, 2, SuppressLevel.values()) + .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) + .withArrayDimension("MTH", (x, sig, idx) -> x.sigs[idx] = sig, 2, Signature.values()) + .run(Warn4::new); } SourceLevel sourceLevel; TrustMe trustMe; - SuppressLevel suppressLevelClient; - SuppressLevel suppressLevelDecl; + SuppressLevel[] suppress = new SuppressLevel[2]; ModifierKind modKind; - Signature vararg_meth; - Signature client_meth; - DiagnosticChecker diagChecker; + Signature[] sigs = new Signature[2]; - public Warn4(SourceLevel sourceLevel, TrustMe trustMe, - SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl, - ModifierKind modKind, Signature vararg_meth, Signature client_meth) { - this.sourceLevel = sourceLevel; - this.trustMe = trustMe; - this.suppressLevelClient = suppressLevelClient; - this.suppressLevelDecl = suppressLevelDecl; - this.modKind = modKind; - this.vararg_meth = vararg_meth; - this.client_meth = client_meth; - this.diagChecker = new DiagnosticChecker(); + boolean badTestFilter() { + return sigs[0].isApplicableTo(sigs[1]); } + final String template = "import java.util.List;\n" + + "class Test {\n" + + " #{TRUSTME} #{SUPPRESS[0]} #{MOD} #{MTH[0].VARARG}\n" + + " #{SUPPRESS[1]} #{MTH[1].CLIENT}\n" + + "}"; + @Override - public void run() { - int id = checkCount.incrementAndGet(); - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - JavaSource source = new JavaSource(id); - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker, - Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey), - null, Arrays.asList(source)); - ct.call(); //to get mandatory notes - check(source, new boolean[] {vararg_meth.giveUnchecked(client_meth), - vararg_meth.giveVarargs(client_meth)}); + public void doWork() throws IOException { + check(newCompilationTask() + .withOption("-Xlint:unchecked") + .withOption("-source") + .withOption(sourceLevel.sourceKey) + .withSourceFromTemplate(template) + .analyze()); } - void check(JavaSource source, boolean[] warnArr) { + void check(Result res) { + boolean[] warnArr = new boolean[] {sigs[0].giveUnchecked(sigs[1]), + sigs[0].giveVarargs(sigs[1])}; + + Set warnings = new HashSet<>(); + for (Diagnostic d : res.diagnosticsForKind(Kind.MANDATORY_WARNING)) { + if (d.getCode().contains(Warning.VARARGS.key)) { + warnings.add(Warning.VARARGS); + } else if(d.getCode().contains(Warning.UNCHECKED.key)) { + warnings.add(Warning.UNCHECKED); + } + } + boolean badOutput = false; for (Warning wkind : Warning.values()) { boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel, - suppressLevelClient, suppressLevelDecl, modKind); + suppress[1], suppress[0], modKind); badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != - diagChecker.warnings.contains(wkind); + warnings.contains(wkind); } if (badOutput) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + "\nExpected unchecked warning: " + warnArr[0] + "\nExpected unsafe vararg warning: " + warnArr[1] + - "\nWarnings: " + diagChecker.warnings + + "\nWarnings: " + warnings + "\nSource level: " + sourceLevel); } } - - class JavaSource extends SimpleJavaFileObject { - - String source; - - public JavaSource(int id) { - super(URI.create(String.format("myfo:/Test%d.java", id)), - JavaFileObject.Kind.SOURCE); - String meth1 = vararg_meth.template.replace("#arity", "..."); - meth1 = meth1.replace("#name", "m"); - meth1 = meth1.replace("#body", ""); - meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() + - modKind.mod + meth1; - String meth2 = client_meth.template.replace("#arity", ""); - meth2 = meth2.replace("#name", "test"); - meth2 = meth2.replace("#body", "m(arg);"); - meth2 = suppressLevelClient.getSuppressAnno() + meth2; - source = String.format("import java.util.List;\n" + - "class Test%s {\n %s \n %s \n } \n", id, meth1, meth2); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - static class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - Set warnings = new HashSet<>(); - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING || - diagnostic.getKind() == Diagnostic.Kind.WARNING) { - if (diagnostic.getCode().contains(Warning.VARARGS.key)) { - warnings.add(Warning.VARARGS); - } else if(diagnostic.getCode().contains(Warning.UNCHECKED.key)) { - warnings.add(Warning.UNCHECKED); - } - } - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 langtools/test/tools/javac/varargs/warning/Warn5.java --- a/langtools/test/tools/javac/varargs/warning/Warn5.java Tue Sep 01 12:57:41 2015 +0300 +++ b/langtools/test/tools/javac/varargs/warning/Warn5.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,29 +26,30 @@ * @bug 6993978 7097436 8006694 7196160 * @summary Project Coin: Annotation to reduce varargs warnings * temporarily workaround combo tests are causing time out in several platforms - * @author mcimadamore - * @library ../../lib - * @modules jdk.compiler - * @build JavacTestingAbstractThreadedTest + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper * @run main/othervm Warn5 */ -// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) -// see JDK-8006746 - -import java.net.URI; -import java.util.Arrays; +import java.io.IOException; import java.util.EnumSet; import javax.tools.Diagnostic; -import javax.tools.JavaCompiler; +import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; -import com.sun.source.util.JavacTask; -public class Warn5 - extends JavacTestingAbstractThreadedTest - implements Runnable { +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + + +public class Warn5 extends ComboInstance { enum XlintOption { NONE("none"), @@ -65,7 +66,7 @@ } } - enum TrustMe { + enum TrustMe implements ComboParameter { DONT_TRUST(""), TRUST("@java.lang.SafeVarargs"); @@ -74,20 +75,26 @@ TrustMe(String anno) { this.anno = anno; } + + @Override + public String expand(String optParameter) { + return anno; + } } - enum SuppressLevel { + enum SuppressLevel implements ComboParameter { NONE, VARARGS; - String getSuppressAnno() { + @Override + public String expand(String optParameter) { return this == VARARGS ? "@SuppressWarnings(\"varargs\")" : ""; } } - enum ModifierKind { + enum ModifierKind implements ComboParameter { NONE(""), FINAL("final"), STATIC("static"), @@ -98,9 +105,14 @@ ModifierKind(String mod) { this.mod = mod; } + + @Override + public String expand(String optParameter) { + return mod; + } } - enum MethodKind { + enum MethodKind implements ComboParameter { METHOD("void m"), CONSTRUCTOR("Test"); @@ -109,6 +121,11 @@ MethodKind(String name) { this.name = name; } + + @Override + public String expand(String optParameter) { + return name; + } } enum SourceLevel { @@ -123,11 +140,11 @@ } } - enum SignatureKind { - VARARGS_X("#K #N(X... x)", false, true), - VARARGS_STRING("#K #N(String... x)", true, true), - ARRAY_X("#K #N(X[] x)", false, false), - ARRAY_STRING("#K #N(String[] x)", true, false); + enum SignatureKind implements ComboParameter { + VARARGS_X("#{NAME}(X... x)", false, true), + VARARGS_STRING("#{NAME}(String... x)", true, true), + ARRAY_X("#{NAME}(X[] x)", false, false), + ARRAY_STRING("#{NAME}(String[] x)", true, false); String stub; boolean isReifiableArg; @@ -139,14 +156,13 @@ this.isVarargs = isVarargs; } - String getSignature(ModifierKind modKind, MethodKind methKind) { - return methKind != MethodKind.CONSTRUCTOR ? - stub.replace("#K", modKind.mod).replace("#N", methKind.name) : - stub.replace("#K", "").replace("#N", methKind.name); + @Override + public String expand(String optParameter) { + return stub; } } - enum BodyKind { + enum BodyKind implements ComboParameter { ASSIGN("Object o = x;", true), CAST("Object o = (Object)x;", true), METH("test(x);", true), @@ -162,82 +178,84 @@ this.body = body; this.hasAliasing = hasAliasing; } + + @Override + public String expand(String optParameter) { + return body; + } } enum WarningKind { - UNSAFE_BODY, - UNSAFE_DECL, - MALFORMED_SAFEVARARGS, - REDUNDANT_SAFEVARARGS; + UNSAFE_BODY("compiler.warn.varargs.unsafe.use.varargs.param"), + UNSAFE_DECL("compiler.warn.unchecked.varargs.non.reifiable.type"), + MALFORMED_SAFEVARARGS("compiler.err.varargs.invalid.trustme.anno"), + REDUNDANT_SAFEVARARGS("compiler.warn.varargs.redundant.trustme.anno"); + + String code; + + WarningKind(String code) { + this.code = code; + } + } + + public static void main(String[] args) { + new ComboTestHelper() + .withFilter(Warn5::badTestFilter) + .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values()) + .withDimension("LINT", (x, lint) -> x.xlint = lint, XlintOption.values()) + .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values()) + .withDimension("SUPPRESS", (x, suppress) -> x.suppressLevel = suppress, SuppressLevel.values()) + .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) + .withDimension("NAME", (x, name) -> x.methKind = name, MethodKind.values()) + .withDimension("SIG", (x, sig) -> x.sig = sig, SignatureKind.values()) + .withDimension("BODY", (x, body) -> x.body = body, BodyKind.values()) + .run(Warn5::new); } - public static void main(String... args) throws Exception { - for (SourceLevel sourceLevel : SourceLevel.values()) { - for (XlintOption xlint : XlintOption.values()) { - for (TrustMe trustMe : TrustMe.values()) { - for (SuppressLevel suppressLevel : SuppressLevel.values()) { - for (ModifierKind modKind : ModifierKind.values()) { - for (MethodKind methKind : MethodKind.values()) { - for (SignatureKind sig : SignatureKind.values()) { - for (BodyKind body : BodyKind.values()) { - pool.execute(new Warn5(sourceLevel, - xlint, trustMe, suppressLevel, - modKind, methKind, sig, body)); - } - } - } - } + SourceLevel sourceLevel; + XlintOption xlint; + TrustMe trustMe; + SuppressLevel suppressLevel; + ModifierKind modKind; + MethodKind methKind; + SignatureKind sig; + BodyKind body; + + boolean badTestFilter() { + return (methKind != MethodKind.CONSTRUCTOR || modKind == ModifierKind.NONE); + } + + String template = "import com.sun.tools.javac.api.*;\n" + + "import java.util.List;\n" + + "class Test {\n" + + " static void test(Object o) {}\n" + + " static void testArr(Object[] o) {}\n" + + " #{TRUSTME} #{SUPPRESS} #{MOD} #{SIG} { #{BODY} }\n" + + "}\n"; + + @Override + public void doWork() throws IOException { + check(newCompilationTask() + .withOption(xlint.getXlintOption()) + .withOption("-source") + .withOption(sourceLevel.sourceKey) + .withSourceFromTemplate(template) + .analyze()); + } + + void check(Result res) { + + EnumSet foundWarnings = EnumSet.noneOf(WarningKind.class); + for (Diagnostic.Kind kind : new Kind[] { Kind.ERROR, Kind.MANDATORY_WARNING, Kind.WARNING}) { + for (Diagnostic diag : res.diagnosticsForKind(kind)) { + for (WarningKind wk : WarningKind.values()) { + if (wk.code.equals(diag.getCode())) { + foundWarnings.add(wk); } } } } - checkAfterExec(false); - } - - final SourceLevel sourceLevel; - final XlintOption xlint; - final TrustMe trustMe; - final SuppressLevel suppressLevel; - final ModifierKind modKind; - final MethodKind methKind; - final SignatureKind sig; - final BodyKind body; - final JavaSource source; - final DiagnosticChecker dc; - - public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, - SuppressLevel suppressLevel, ModifierKind modKind, - MethodKind methKind, SignatureKind sig, BodyKind body) { - this.sourceLevel = sourceLevel; - this.xlint = xlint; - this.trustMe = trustMe; - this.suppressLevel = suppressLevel; - this.modKind = modKind; - this.methKind = methKind; - this.sig = sig; - this.body = body; - this.source = new JavaSource(); - this.dc = new DiagnosticChecker(); - } - - @Override - public void run() { - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, - Arrays.asList(xlint.getXlintOption(), - "-source", sourceLevel.sourceKey), - null, Arrays.asList(source)); - try { - ct.analyze(); - } catch (Throwable t) { - processException(t); - } - check(); - } - - void check() { - EnumSet expectedWarnings = EnumSet.noneOf(WarningKind.class); @@ -284,77 +302,14 @@ expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS); } - if (!expectedWarnings.containsAll(dc.warnings) || - !dc.warnings.containsAll(expectedWarnings)) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + + if (!expectedWarnings.containsAll(foundWarnings) || + !foundWarnings.containsAll(expectedWarnings)) { + fail("invalid diagnostics for source:\n" + + res.compilationInfo() + "\nOptions: " + xlint.getXlintOption() + "\nSource Level: " + sourceLevel + "\nExpected warnings: " + expectedWarnings + - "\nFound warnings: " + dc.warnings); - } - } - - class JavaSource extends SimpleJavaFileObject { - - String template = "import com.sun.tools.javac.api.*;\n" + - "import java.util.List;\n" + - "class Test {\n" + - " static void test(Object o) {}\n" + - " static void testArr(Object[] o) {}\n" + - " #T \n #S #M { #B }\n" + - "}\n"; - - String source; - - public JavaSource() { - super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); - source = template.replace("#T", trustMe.anno). - replace("#S", suppressLevel.getSuppressAnno()). - replace("#M", sig.getSignature(modKind, methKind)). - replace("#B", body.body); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; + "\nFound warnings: " + foundWarnings); } } - - class DiagnosticChecker - implements javax.tools.DiagnosticListener { - - EnumSet warnings = EnumSet.noneOf(WarningKind.class); - - public void report(Diagnostic diagnostic) { - if (diagnostic.getKind() == Diagnostic.Kind.WARNING) { - if (diagnostic.getCode(). - contains("unsafe.use.varargs.param")) { - setWarning(WarningKind.UNSAFE_BODY); - } else if (diagnostic.getCode(). - contains("redundant.trustme")) { - setWarning(WarningKind.REDUNDANT_SAFEVARARGS); - } - } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING && - diagnostic.getCode(). - contains("varargs.non.reifiable.type")) { - setWarning(WarningKind.UNSAFE_DECL); - } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR && - diagnostic.getCode().contains("invalid.trustme")) { - setWarning(WarningKind.MALFORMED_SAFEVARARGS); - } - } - - void setWarning(WarningKind wk) { - if (!warnings.add(wk)) { - throw new AssertionError("Duplicate warning of kind " + - wk + " in source:\n" + source); - } - } - - boolean hasWarning(WarningKind wk) { - return warnings.contains(wk); - } - } - } diff -r 23b29549f8d1 -r 54fbe836fcf0 make/Init.gmk --- a/make/Init.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/make/Init.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -253,6 +253,7 @@ main: $(INIT_TARGETS) ifneq ($(SEQUENTIAL_TARGETS)$(PARALLEL_TARGETS), ) $(call RotateLogFiles) + $(call PrepareFailureLogs) $(BUILD_LOG_WRAPPER) $(PRINTF) "Building $(TARGET_DESCRIPTION)\n" ifneq ($(SEQUENTIAL_TARGETS), ) # Don't touch build output dir since we might be cleaning. That @@ -266,10 +267,13 @@ $(call PrepareSmartJavac) ( cd $(TOPDIR) && \ $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \ - -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \ - $(PARALLEL_TARGETS) || \ - ( exitcode=$$? && $(BUILD_LOG_WRAPPER) $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" && \ - $(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors \n\n" && exit $$exitcode ) ) + -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \ + $(PARALLEL_TARGETS) || \ + ( exitcode=$$? && $(BUILD_LOG_WRAPPER) \ + $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" && \ + cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -j 1 -f make/Init.gmk \ + HAS_SPEC=true on-failure ; \ + exit $$exitcode ) ) $(call CleanupSmartJavac) $(call StopGlobalTimer) $(call ReportBuildTimes) @@ -277,5 +281,25 @@ $(BUILD_LOG_WRAPPER) $(PRINTF) "Finished building $(TARGET_DESCRIPTION)\n" endif - .PHONY: print-targets print-modules reconfigure main + on-failure: + ifneq ($(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), ) + $(PRINTF) "=== Output from failing command(s) repeated here ===\n" + $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \ + $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \ + $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \ + ) + $(PRINTF) "=== End of repeated output ===\n" + endif + if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \ + $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \ + $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \ + $(PRINTF) "=== End of repeated output ===\n" ; \ + $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \ + else \ + $(PRINTF) "No indication of failed target found.\n" ; \ + $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \ + fi + $(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n" + + .PHONY: print-targets print-modules reconfigure main on-failure endif diff -r 23b29549f8d1 -r 54fbe836fcf0 make/InitSupport.gmk --- a/make/InitSupport.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/make/InitSupport.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -318,6 +318,11 @@ ) endef + define PrepareFailureLogs + $(RM) -r $(MAKESUPPORT_OUTPUTDIR)/failure-logs 2> /dev/null + $(MKDIR) -p $(MAKESUPPORT_OUTPUTDIR)/failure-logs + endef + # Remove any javac server logs and port files. This # prevents a new make run to reuse the previous servers. define PrepareSmartJavac diff -r 23b29549f8d1 -r 54fbe836fcf0 make/common/JavaCompilation.gmk --- a/make/common/JavaCompilation.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/make/common/JavaCompilation.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -563,18 +563,19 @@ $(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE)) $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp) $(ECHO) Compiling $1 - ($$($1_JVM) $$($1_SJAVAC) \ - $$($1_REMOTE) \ - -j 1 \ - --permit-unidentified-artifacts \ - --permit-sources-without-package \ - --compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \ - --log=$(LOG_LEVEL) \ - $$($1_SJAVAC_ARGS) \ - $$($1_FLAGS) \ - $$($1_HEADERS_ARG) \ - -d $$($1_BIN) && \ - $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch) + $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \ + $$($1_JVM) $$($1_SJAVAC) \ + $$($1_REMOTE) \ + -j 1 \ + --permit-unidentified-artifacts \ + --permit-sources-without-package \ + --compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \ + --log=$(LOG_LEVEL) \ + $$($1_SJAVAC_ARGS) \ + $$($1_FLAGS) \ + $$($1_HEADERS_ARG) \ + -d $$($1_BIN)) && \ + $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch # Create a pubapi file that only changes when the pubapi changes. Dependent # compilations can use this file to only get recompiled when pubapi has changed. # Grep returns 1 if no matching lines are found. Do not fail for this. @@ -619,11 +620,11 @@ $(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp) $(ECHO) Compiling `$(WC) $$($1_BIN)/_the.$1_batch.tmp | $(TR) -s ' ' | $(CUT) -f 2 -d ' '` files for $1 - ($$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \ - -implicit:none \ - -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp && \ - $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch) - + $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \ + $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \ + -implicit:none \ + -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp) && \ + $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch endif # Add all targets to main variable diff -r 23b29549f8d1 -r 54fbe836fcf0 make/common/MakeBase.gmk --- a/make/common/MakeBase.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/make/common/MakeBase.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -755,6 +755,20 @@ $(call DependOnVariableHelper,$(strip $1),$(strip $2)) ################################################################################ +# Failure logging support macros. These are supposed to be used by the Setup* +# compilation macros. +# +# LogFailures will run a command and store a copy of output in a specified file. +# If the command succeeds, the file is deleted, otherwise it is moved to the +# failure-logs directory. +# Param 1 - The log file of the failed command +# Param 2 - A compact but representative name to describe this command +# Param 3 - Command to run +LogFailures = \ + ( ($(BASH) $(SRC_ROOT)/common/bin/logger.sh $1 $3 && $(RM) $1) || \ + (exitcode=$(DOLLAR)$(DOLLAR)? && $(MV) $1 $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(strip $2).log && exit $(DOLLAR)$(DOLLAR)exitcode) ) + +################################################################################ # Find lib dir for module # Param 1 - module name ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) diff -r 23b29549f8d1 -r 54fbe836fcf0 make/common/NativeCompilation.gmk --- a/make/common/NativeCompilation.gmk Tue Sep 01 12:57:41 2015 +0300 +++ b/make/common/NativeCompilation.gmk Tue Sep 08 15:39:51 2015 -0700 @@ -201,23 +201,25 @@ $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) | $$($1_BUILD_INFO) $(ECHO) $(LOG_INFO) "Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET)))" ifneq ($(TOOLCHAIN_TYPE), microsoft) - # The Solaris studio compiler doesn't output the full path to the object file in the - # generated deps files. Fixing it with sed. If compiling assembly, don't try this. ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio) - $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 + # The Solaris studio compiler doesn't output the full path to the object file in the + # generated deps files. Fixing it with sed. If compiling assembly, don't try this. + $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \ + $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) $(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP) else - $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 + $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \ + $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) endif - endif - # The Visual Studio compiler lacks a feature for generating make dependencies, but by - # setting -showIncludes, all included files are printed. These are filtered out and - # parsed into make dependences. - ifeq ($(TOOLCHAIN_TYPE), microsoft) - ($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ - $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \ + else + # The Visual Studio compiler lacks a feature for generating make dependencies, but by + # setting -showIncludes, all included files are printed. These are filtered out and + # parsed into make dependences. + ($(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \ + $$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ + $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) ; echo $$$$? > $$($1_$2_DEP).exitvalue) \ | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \ - -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \ + -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \ exit `cat $$($1_$2_DEP).exitvalue` $(RM) $$($1_$2_DEP).exitvalue ($(ECHO) $$@: \\ \ @@ -694,10 +696,11 @@ $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \ $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE) $(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)" - $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ + $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \ + $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ $(LD_OUT_OPTION)$$@ \ $$($1_EXPECTED_OBJS) $$($1_RES) \ - $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX) + $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)) $$($1_CREATE_DEBUGINFO_CMDS) # Touch target to make sure it has a later time stamp than the debug # symbol files to avoid unnecessary relinking on rebuild. @@ -716,8 +719,9 @@ # Generating a static library, ie object file archive. $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)" - $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \ - $$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX) + $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \ + $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \ + $$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)) endif ifneq (,$$($1_PROGRAM)) @@ -733,10 +737,11 @@ $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_MANIFEST) \ $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE) $(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)" - $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ - $(EXE_OUT_OPTION)$$($1_TARGET) \ - $$($1_EXPECTED_OBJS) $$($1_RES) \ - $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX) + $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \ + $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ + $(EXE_OUT_OPTION)$$($1_TARGET) \ + $$($1_EXPECTED_OBJS) $$($1_RES) \ + $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)) ifeq ($(OPENJDK_TARGET_OS), windows) ifneq ($$($1_MANIFEST), ) $$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_PROGRAM).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1 diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/.hgtags --- a/nashorn/.hgtags Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/.hgtags Tue Sep 08 15:39:51 2015 -0700 @@ -313,3 +313,4 @@ 33cecbc59f2ad78ac0934cbc3e014d346077e848 jdk9-b77 6f634e84387e97b2421d5e776e46935784156d1c jdk9-b78 9b3eca69b88b2d1bebce92d58280ae66fc0b6091 jdk9-b79 +61b401b23fc28208930977d46b690423911173c6 jdk9-b80 diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/make/project.properties --- a/nashorn/make/project.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/make/project.properties Tue Sep 08 15:39:51 2015 -0700 @@ -302,7 +302,7 @@ -XX:+HeapDumpOnOutOfMemoryError # turn on assertions for tests -run.test.jvmargs.main=${run.test.jvmargs.common} -esa -ea +run.test.jvmargs.main=${run.test.jvmargs.common} -esa -ea -da:java.lang.invoke.LambdaFormEditor # Extra jvmargs that might be useful for debugging # and performance improvements/monitoring diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Tue Sep 08 15:39:51 2015 -0700 @@ -107,7 +107,7 @@ private final AccessibleObject target; private final MethodType type; - public CallerSensitiveDynamicMethod(final AccessibleObject target) { + CallerSensitiveDynamicMethod(final AccessibleObject target) { super(getName(target)); this.target = target; this.type = getMethodType(target); @@ -115,8 +115,9 @@ private static String getName(final AccessibleObject target) { final Member m = (Member)target; - return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(), - m.getName())); + final boolean constructor = m instanceof Constructor; + return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() : + getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor); } @Override diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Tue Sep 08 15:39:51 2015 -0700 @@ -86,7 +86,9 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.text.Collator; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -242,6 +244,35 @@ return methods.getFirst().isConstructor(); } + @Override + public String toString() { + // First gather the names and sort them. This makes it consistent and easier to read. + final List names = new ArrayList<>(methods.size()); + int len = 0; + for (final SingleDynamicMethod m: methods) { + final String name = m.getName(); + len += name.length(); + names.add(name); + } + // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean". + final Collator collator = Collator.getInstance(); + collator.setStrength(Collator.SECONDARY); + Collections.sort(names, collator); + + final String className = getClass().getName(); + // Class name length + length of signatures + 2 chars/per signature for indentation and newline + + // 3 for brackets and initial newline + final int totalLength = className.length() + len + 2 * names.size() + 3; + final StringBuilder b = new StringBuilder(totalLength); + b.append('[').append(className).append('\n'); + for(final String name: names) { + b.append(' ').append(name).append('\n'); + } + b.append(']'); + assert b.length() == totalLength; + return b.toString(); + }; + ClassLoader getClassLoader() { return classLoader; } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Tue Sep 08 15:39:51 2015 -0700 @@ -122,13 +122,13 @@ * @param constructor does this represent a constructor? */ SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { - super(getName(target, clazz, name)); + super(getName(target, clazz, name, constructor)); this.target = target; this.constructor = constructor; } - private static String getName(final MethodHandle target, final Class clazz, final String name) { - return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name)); + private static String getName(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { + return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor); } @Override diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Tue Sep 08 15:39:51 2015 -0700 @@ -143,14 +143,18 @@ return getMethodType().parameterList().equals(method.getMethodType().parameterList()); } - static String getMethodNameWithSignature(final MethodType type, final String methodName) { + static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) { final String typeStr = type.toString(); final int retTypeIndex = typeStr.lastIndexOf(')') + 1; int secondParamIndex = typeStr.indexOf(',') + 1; if(secondParamIndex == 0) { secondParamIndex = retTypeIndex - 1; } - return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex); + final StringBuilder b = new StringBuilder(); + if (withReturnType) { + b.append(typeStr, retTypeIndex, typeStr.length()).append(' '); + } + return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString(); } /** diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Tue Sep 08 15:39:51 2015 -0700 @@ -51,6 +51,8 @@ private String fileName; // script line number private int line; + // are the line and fileName unknown? + private boolean lineAndFileNameUnknown; // script column number private int column; // underlying ECMA error object - lazily initialized @@ -92,27 +94,10 @@ */ protected NashornException(final String msg, final Throwable cause) { super(msg, cause == null ? null : cause); - // This is not so pretty - but it gets the job done. Note that the stack - // trace has been already filled by "fillInStackTrace" call from - // Throwable - // constructor and so we don't pay additional cost for it. - // Hard luck - no column number info this.column = -1; - - // Find the first JavaScript frame by walking and set file, line from it - // Usually, we should be able to find it in just few frames depth. - for (final StackTraceElement ste : getStackTrace()) { - if (ECMAErrors.isScriptFrame(ste)) { - // Whatever here is compiled from JavaScript code - this.fileName = ste.getFileName(); - this.line = ste.getLineNumber(); - return; - } - } - - this.fileName = null; - this.line = 0; + // We can retrieve the line number and file name from the stack trace if needed + this.lineAndFileNameUnknown = true; } /** @@ -121,6 +106,7 @@ * @return the file name */ public final String getFileName() { + ensureLineAndFileName(); return fileName; } @@ -131,6 +117,7 @@ */ public final void setFileName(final String fileName) { this.fileName = fileName; + lineAndFileNameUnknown = false; } /** @@ -139,6 +126,7 @@ * @return the line number */ public final int getLineNumber() { + ensureLineAndFileName(); return line; } @@ -148,6 +136,7 @@ * @param line the line number */ public final void setLineNumber(final int line) { + lineAndFileNameUnknown = false; this.line = line; } @@ -274,4 +263,19 @@ public void setEcmaError(final Object ecmaError) { this.ecmaError = ecmaError; } + + private void ensureLineAndFileName() { + if (lineAndFileNameUnknown) { + for (final StackTraceElement ste : getStackTrace()) { + if (ECMAErrors.isScriptFrame(ste)) { + // Whatever here is compiled from JavaScript code + fileName = ste.getFileName(); + line = ste.getLineNumber(); + return; + } + } + + lineAndFileNameUnknown = false; + } + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Tue Sep 08 15:39:51 2015 -0700 @@ -283,17 +283,13 @@ start++; } - start++; //we always uses this + start++; // we always use this - final List params = functionNode.getParameters(); + assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!"; final List newParams = new ArrayList<>(); - final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start); + final long to = actualCallSiteType.parameterCount() - start; for (int i = 0; i < to; i++) { - if (i >= params.size()) { - newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i))); - } else { - newParams.add(params.get(i)); - } + newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i))); } callSiteTypes.push(actualCallSiteType); @@ -316,6 +312,10 @@ return false; } + if (functionNode.getNumOfParams() != 0) { + return false; + } + if (functionNode.hasEval()) { return false; } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Tue Sep 08 15:39:51 2015 -0700 @@ -149,12 +149,14 @@ private final Deque> thisProperties = new ArrayDeque<>(); private final Map globalSymbols = new HashMap<>(); //reuse the same global symbol private final Compiler compiler; + private final boolean isOnDemand; public AssignSymbols(final Compiler compiler) { super(new LexicalContext()); this.compiler = compiler; this.log = initLogger(compiler.getContext()); this.debug = log.isEnabled(); + this.isOnDemand = compiler.isOnDemandCompilation(); } @Override @@ -390,7 +392,7 @@ // Create and add to appropriate block. symbol = createSymbol(name, flags); - symbolBlock.putSymbol(lc, symbol); + symbolBlock.putSymbol(symbol); if ((flags & IS_SCOPE) == 0) { // Initial assumption; symbol can lose its slot later @@ -440,7 +442,7 @@ start(block); if (lc.isFunctionBody()) { - block.clearSymbols(); + assert !block.hasSymbols(); final FunctionNode fn = lc.getCurrentFunction(); if (isUnparsedFunction(fn)) { // It's a skipped nested function. Just mark the symbols being used by it as being in use. @@ -459,7 +461,7 @@ } private boolean isUnparsedFunction(final FunctionNode fn) { - return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction(); + return isOnDemand && fn != lc.getOutermostFunction(); } @Override @@ -747,28 +749,6 @@ } } - @Override - public Node leaveBlock(final Block block) { - // It's not necessary to guard the marking of symbols as locals with this "if" condition for - // correctness, it's just an optimization -- runtime type calculation is not used when the compilation - // is not an on-demand optimistic compilation, so we can skip locals marking then. - if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { - // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand - // compilation, and we're skipping parsing the function bodies for nested functions, this - // basically only means their parameters. It'd be enough to mistakenly declare to be a local a - // symbol in the outer function named the same as one of the parameters, though. - if (lc.getFunction(block) == lc.getOutermostFunction()) { - for (final Symbol symbol: block.getSymbols()) { - if (!symbol.isScope()) { - assert symbol.isVar() || symbol.isParam(); - compiler.declareLocalSymbol(symbol.getName()); - } - } - } - } - return block; - } - private Node leaveDELETE(final UnaryNode unaryNode) { final FunctionNode currentFunctionNode = lc.getCurrentFunction(); final boolean strictMode = currentFunctionNode.isStrict(); @@ -786,9 +766,9 @@ if (symbol.isThis()) { // Can't delete "this", ignore and return true - return LiteralNode.newInstance(unaryNode, true).accept(this); + return LiteralNode.newInstance(unaryNode, true); } - final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); + final Expression literalNode = LiteralNode.newInstance(unaryNode, name); final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); if (!failDelete) { @@ -799,7 +779,7 @@ if (failDelete) { request = Request.FAIL_DELETE; - } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) { + } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) { request = Request.SLOW_DELETE; } } else if (rhs instanceof AccessNode) { @@ -807,7 +787,7 @@ final String property = ((AccessNode)rhs).getProperty(); args.add(base); - args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this)); + args.add(LiteralNode.newInstance(unaryNode, property)); args.add(strictFlagNode); } else if (rhs instanceof IndexNode) { @@ -820,15 +800,15 @@ args.add(strictFlagNode); } else { - return LiteralNode.newInstance(unaryNode, true).accept(this); + return LiteralNode.newInstance(unaryNode, true); } - return new RuntimeNode(unaryNode, request, args).accept(this); + return new RuntimeNode(unaryNode, request, args); } @Override public Node leaveForNode(final ForNode forNode) { if (forNode.isForIn()) { - forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 + return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 } return end(forNode); @@ -904,19 +884,18 @@ public Node leaveSwitchNode(final SwitchNode switchNode) { // We only need a symbol for the tag if it's not an integer switch node if(!switchNode.isUniqueInteger()) { - switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX)); + return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX)); } return switchNode; } @Override public Node leaveTryNode(final TryNode tryNode) { - tryNode.setException(exceptionSymbol()); assert tryNode.getFinallyBody() == null; end(tryNode); - return tryNode; + return tryNode.setException(lc, exceptionSymbol()); } private Node leaveTYPEOF(final UnaryNode unaryNode) { @@ -925,13 +904,13 @@ final List args = new ArrayList<>(); if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { args.add(compilerConstantIdentifier(SCOPE)); - args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null + args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null } else { args.add(rhs); - args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' + args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' } - final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this); + final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); end(unaryNode); @@ -939,7 +918,7 @@ } private FunctionNode markProgramBlock(final FunctionNode functionNode) { - if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) { + if (isOnDemand || !functionNode.isProgram()) { return functionNode; } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.nashorn.internal.codegen; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.util.Collections; -import java.util.zip.Deflater; -import java.util.zip.DeflaterOutputStream; -import jdk.nashorn.internal.ir.Block; -import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.LexicalContext; -import jdk.nashorn.internal.ir.Node; -import jdk.nashorn.internal.ir.Statement; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; -import jdk.nashorn.internal.runtime.options.Options; - -/** - * This static utility class performs serialization of FunctionNode ASTs to a byte array. - * The format is a standard Java serialization stream, deflated. - */ -final class AstSerializer { - // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed - // and size. - private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4); - static byte[] serialize(final FunctionNode fn) { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final Deflater deflater = new Deflater(COMPRESSION_LEVEL); - try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) { - oout.writeObject(removeInnerFunctionBodies(fn)); - } catch (final IOException e) { - throw new AssertionError("Unexpected exception serializing function", e); - } finally { - deflater.end(); - } - return out.toByteArray(); - } - - private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) { - return (FunctionNode)fn.accept(new NodeVisitor(new LexicalContext()) { - @Override - public Node leaveBlock(final Block block) { - if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) { - return block.setStatements(lc, Collections.emptyList()); - } - return super.leaveBlock(block); - } - }); - } -} diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CacheAst.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CacheAst.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.codegen; + +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.LexicalContext; +import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.Statement; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; + +class CacheAst extends NodeVisitor { + private final Deque dataStack = new ArrayDeque<>(); + + private final Compiler compiler; + + CacheAst(final Compiler compiler) { + super(new LexicalContext()); + this.compiler = compiler; + assert !compiler.isOnDemandCompilation(); + } + + @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + final int id = functionNode.getId(); + // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a + // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way + // we keep it constant time. + dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id)); + return true; + } + + @Override + public Node leaveFunctionNode(final FunctionNode functionNode) { + final RecompilableScriptFunctionData data = dataStack.pop(); + if (functionNode.isSplit()) { + // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require + // some additional work, namely creating the concept of "uncacheable" function and reworking + // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not + // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST. + // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the + // function being cached (and not reflect uses from its own nested functions or functions it is + // nested in). This is consistent with the count an on-demand recompilation of the function would + // produce. This is important as the decision to emit shared scope calls is based on this count, + // and if it is not matched between a previous version of the code and its deoptimizing rest-of + // compilation, it can result in rest-of not emitting a shared scope call where a previous version + // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit + // it, causing a mismatch in stack shapes between previous code and its rest-of. + data.setCachedAst(functionNode); + } + + if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) { + // Return a function node with no body so that caching outer functions doesn't hold on to nested + // functions' bodies. Note we're doing this only for functions directly nested inside split + // functions, since we're only caching the split ones. It is not necessary to limit body removal + // to just these functions, but it's a cheap way to prevent unnecessary AST mutations. + return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.emptyList())); + } + return functionNode; + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Sep 08 15:39:51 2015 -0700 @@ -48,11 +48,13 @@ import java.util.Set; import jdk.nashorn.internal.AssertsEnabled; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; +import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.Symbol; import jdk.nashorn.internal.ir.debug.ASTWriter; import jdk.nashorn.internal.ir.debug.PrintVisitor; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -189,7 +191,7 @@ } }, - SERIALIZE_SPLIT_PHASE( + CACHE_AST( EnumSet.of( INITIALIZED, PARSED, @@ -199,20 +201,21 @@ SPLIT)) { @Override FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { - return transformFunction(fn, new NodeVisitor(new LexicalContext()) { - @Override - public boolean enterFunctionNode(final FunctionNode functionNode) { - if (functionNode.isSplit()) { - compiler.serializeAst(functionNode); - } - return true; - } - }); + if (!compiler.isOnDemandCompilation()) { + // Only do this on initial preprocessing of the source code. For on-demand compilations from + // source, FindScopeDepths#leaveFunctionNode() calls data.setCachedAst() for the sole function + // being compiled. + transformFunction(fn, new CacheAst(compiler)); + } + // NOTE: we're returning the original fn as we have destructively modified the cached functions by + // removing their bodies. This step is associating FunctionNode objects with + // RecompilableScriptFunctionData; it's not really modifying the AST. + return fn; } @Override public String toString() { - return "'Serialize Split Functions'"; + return "'Cache ASTs'"; } }, @@ -255,6 +258,51 @@ } }, + DECLARE_LOCAL_SYMBOLS_TO_COMPILER( + EnumSet.of( + INITIALIZED, + PARSED, + CONSTANT_FOLDED, + LOWERED, + BUILTINS_TRANSFORMED, + SPLIT, + SYMBOLS_ASSIGNED, + SCOPE_DEPTHS_COMPUTED)) { + @Override + FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { + // It's not necessary to guard the marking of symbols as locals with this "if" condition for + // correctness, it's just an optimization -- runtime type calculation is not used when the compilation + // is not an on-demand optimistic compilation, so we can skip locals marking then. + if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { + fn.getBody().accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand + // compilation, and we're skipping parsing the function bodies for nested functions, this + // basically only means their parameters. It'd be enough to mistakenly declare to be a local a + // symbol in the outer function named the same as one of the parameters, though. + return false; + }; + @Override + public boolean enterBlock(final Block block) { + for (final Symbol symbol: block.getSymbols()) { + if (!symbol.isScope()) { + compiler.declareLocalSymbol(symbol.getName()); + } + } + return true; + }; + }); + } + return fn; + } + + @Override + public String toString() { + return "'Local Symbols Declaration'"; + } + }, + OPTIMISTIC_TYPE_ASSIGNMENT_PHASE( EnumSet.of( INITIALIZED, @@ -382,7 +430,7 @@ } }, - REINITIALIZE_SERIALIZED( + REINITIALIZE_CACHED( EnumSet.of( INITIALIZED, PARSED, @@ -430,7 +478,7 @@ @Override public String toString() { - return "'Deserialize'"; + return "'Reinitialize cached'"; } }, diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Tue Sep 08 15:39:51 2015 -0700 @@ -160,42 +160,41 @@ */ private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32; - private final Map serializedAsts = new HashMap<>(); - /** * Compilation phases that a compilation goes through */ public static class CompilationPhases implements Iterable { /** - * Singleton that describes compilation up to the phase where a function can be serialized. + * Singleton that describes compilation up to the phase where a function can be cached. */ - private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases( + private final static CompilationPhases COMPILE_UPTO_CACHED = new CompilationPhases( "Common initial phases", CompilationPhase.CONSTANT_FOLDING_PHASE, CompilationPhase.LOWERING_PHASE, CompilationPhase.TRANSFORM_BUILTINS_PHASE, CompilationPhase.SPLITTING_PHASE, CompilationPhase.PROGRAM_POINT_PHASE, - CompilationPhase.SERIALIZE_SPLIT_PHASE + CompilationPhase.SYMBOL_ASSIGNMENT_PHASE, + CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE, + CompilationPhase.CACHE_AST ); - private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases( + private final static CompilationPhases COMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases( "After common phases, before bytecode generator", - CompilationPhase.SYMBOL_ASSIGNMENT_PHASE, - CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE, + CompilationPhase.DECLARE_LOCAL_SYMBOLS_TO_COMPILER, CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE, CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE ); /** - * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not - * including) generating and installing code. + * Singleton that describes additional steps to be taken after retrieving a cached function, all the + * way up to (but not including) generating and installing code. */ - public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases( - "Recompile serialized function up to bytecode", - CompilationPhase.REINITIALIZE_SERIALIZED, - COMPILE_SERIALIZABLE_UPTO_BYTECODE + public final static CompilationPhases RECOMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases( + "Recompile cached function up to bytecode", + CompilationPhase.REINITIALIZE_CACHED, + COMPILE_CACHED_UPTO_BYTECODE ); /** @@ -211,8 +210,8 @@ /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */ public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases( "Compile upto bytecode", - COMPILE_UPTO_SERIALIZABLE, - COMPILE_SERIALIZABLE_UPTO_BYTECODE); + COMPILE_UPTO_CACHED, + COMPILE_CACHED_UPTO_BYTECODE); /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */ public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases( @@ -227,9 +226,9 @@ GENERATE_BYTECODE_AND_INSTALL); /** Singleton that describes a full compilation - this includes code installation - from serialized state*/ - public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases( + public final static CompilationPhases COMPILE_ALL_CACHED = new CompilationPhases( "Eager compilation from serializaed state", - RECOMPILE_SERIALIZED_UPTO_BYTECODE, + RECOMPILE_CACHED_UPTO_BYTECODE, GENERATE_BYTECODE_AND_INSTALL); /** @@ -248,9 +247,9 @@ GENERATE_BYTECODE_AND_INSTALL_RESTOF); /** Compile from serialized for a rest of method */ - public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases( + public final static CompilationPhases COMPILE_CACHED_RESTOF = new CompilationPhases( "Compile serialized, rest of", - RECOMPILE_SERIALIZED_UPTO_BYTECODE, + RECOMPILE_CACHED_UPTO_BYTECODE, GENERATE_BYTECODE_AND_INSTALL_RESTOF); private final List phases; @@ -313,7 +312,7 @@ } boolean isRestOfCompilation() { - return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF; + return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_CACHED_RESTOF; } String getDesc() { @@ -766,14 +765,6 @@ compileUnits.addAll(newUnits); } - void serializeAst(final FunctionNode fn) { - serializedAsts.put(fn.getId(), AstSerializer.serialize(fn)); - } - - byte[] removeSerializedAst(final int fnId) { - return serializedAsts.remove(fnId); - } - CompileUnit findUnit(final long weight) { for (final CompileUnit unit : compileUnits) { if (unit.canHold(weight)) { diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Tue Sep 08 15:39:51 2015 -0700 @@ -188,6 +188,9 @@ log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope."); newFunctionNode = newFunctionNode.setInDynamicContext(lc); } + if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) { + data.setCachedAst(newFunctionNode); + } return newFunctionNode; } @@ -208,8 +211,7 @@ ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()), nestedFunctions, externalSymbolDepths.get(fnId), - internalSymbols.get(fnId), - compiler.removeSerializedAst(fnId)); + internalSymbols.get(fnId)); if (lc.getOutermostFunction() != newFunctionNode) { final FunctionNode parentFn = lc.getParentFunction(newFunctionNode); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Tue Sep 08 15:39:51 2015 -0700 @@ -497,7 +497,7 @@ private transient Label.Stack stack; /** ASM representation of this label */ - private jdk.internal.org.objectweb.asm.Label label; + private transient jdk.internal.org.objectweb.asm.Label label; /** Id for debugging purposes, remove if footprint becomes unmanageable */ private final int id; diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeMap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeMap.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeMap.java Tue Sep 08 15:39:51 2015 -0700 @@ -27,21 +27,18 @@ import java.lang.invoke.MethodType; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.NoSuchElementException; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.runtime.ScriptFunction; /** - * A data structure that maps one or several function nodes (by their unique id:s, not by - * the FunctionNode object itself, due to copy on write changing it several times through - * code generation. + * A tuple containing function id, parameter types, return type and needsCallee flag. */ -public class TypeMap { - private final Map paramTypeMap = new HashMap<>(); - private final Map returnTypeMap = new HashMap<>(); +public final class TypeMap { + private final int functionNodeId; + private final Type[] paramTypes; + private final Type returnType; private final boolean needsCallee; /** @@ -56,9 +53,10 @@ for (final Class p : type.parameterArray()) { types[pos++] = Type.typeFor(p); } - paramTypeMap.put(functionNodeId, types); - returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType())); + this.functionNodeId = functionNodeId; + this.paramTypes = types; + this.returnType = Type.typeFor(type.returnType()); this.needsCallee = needsCallee; } @@ -69,20 +67,14 @@ * @throws NoSuchElementException if the type map has no mapping for the requested function */ public Type[] getParameterTypes(final int functionNodeId) { - final Type[] paramTypes = paramTypeMap.get(functionNodeId); - if (paramTypes == null) { - throw new NoSuchElementException(Integer.toString(functionNodeId)); - } + assert this.functionNodeId == functionNodeId; return paramTypes.clone(); } MethodType getCallSiteType(final FunctionNode functionNode) { - final Type[] types = paramTypeMap.get(functionNode.getId()); - if (types == null) { - return null; - } - - MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass()); + assert this.functionNodeId == functionNode.getId(); + final Type[] types = paramTypes; + MethodType mt = MethodType.methodType(returnType.getTypeClass()); if (needsCallee) { mt = mt.appendParameterTypes(ScriptFunction.class); } @@ -116,7 +108,8 @@ * @return parameter type for this callsite if known */ Type get(final FunctionNode functionNode, final int pos) { - final Type[] types = paramTypeMap.get(functionNode.getId()); + assert this.functionNodeId == functionNode.getId(); + final Type[] types = paramTypes; assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this; if (types != null && pos < types.length) { return types[pos]; @@ -124,13 +117,6 @@ return null; } - boolean has(final FunctionNode functionNode) { - final int id = functionNode.getId(); - final Type[] paramTypes = paramTypeMap.get(id); - assert (paramTypes == null) == (returnTypeMap.get(id) == null) : "inconsistent param and return types in param map"; - return paramTypes != null; - } - @Override public String toString() { return toString(""); @@ -139,27 +125,16 @@ String toString(final String prefix) { final StringBuilder sb = new StringBuilder(); - if (paramTypeMap.isEmpty()) { - sb.append(prefix).append("\t"); - return sb.toString(); - } - - for (final Map.Entry entry : paramTypeMap.entrySet()) { - final int id = entry.getKey(); - sb.append(prefix).append('\t'); - sb.append("function ").append(id).append('\n'); - sb.append(prefix).append("\t\tparamTypes="); - if (entry.getValue() == null) { - sb.append("[]"); - } else { - sb.append(Arrays.toString(entry.getValue())); - } - sb.append('\n'); - sb.append(prefix).append("\t\treturnType="); - final Type ret = returnTypeMap.get(id); - sb.append(ret == null ? "N/A" : ret); - sb.append('\n'); - } + final int id = functionNodeId; + sb.append(prefix).append('\t'); + sb.append("function ").append(id).append('\n'); + sb.append(prefix).append("\t\tparamTypes="); + sb.append(Arrays.toString(paramTypes)); + sb.append('\n'); + sb.append(prefix).append("\t\treturnType="); + final Type ret = returnType; + sb.append(ret == null ? "N/A" : ret); + sb.append('\n'); return sb.toString(); } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Tue Sep 08 15:39:51 2015 -0700 @@ -159,11 +159,42 @@ } /** - * Clear the symbols in the block. - * TODO: make this immutable. + * Returns true if this block defines any symbols. + * @return true if this block defines any symbols. + */ + public boolean hasSymbols() { + return !symbols.isEmpty(); + } + + /** + * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are + * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the + * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols. + * Those should be updated separately as this method is meant to be used as part of such an update pass. + * @param lc the current lexical context + * @param replacements the map of symbol replacements + * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol + * table. */ - public void clearSymbols() { - symbols.clear(); + public Block replaceSymbols(final LexicalContext lc, final Map replacements) { + if (symbols.isEmpty()) { + return this; + } + final LinkedHashMap newSymbols = new LinkedHashMap<>(symbols); + for (final Map.Entry entry: newSymbols.entrySet()) { + final Symbol newSymbol = replacements.get(entry.getValue()); + assert newSymbol != null : "Missing replacement for " + entry.getKey(); + entry.setValue(newSymbol); + } + return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion)); + } + + /** + * Returns a copy of this block with a shallow copy of the symbol table. + * @return a copy of this block with a shallow copy of the symbol table. + */ + public Block copyWithNewSymbols() { + return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion); } @Override @@ -191,7 +222,7 @@ * @return symbol iterator */ public List getSymbols() { - return Collections.unmodifiableList(new ArrayList<>(symbols.values())); + return symbols.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values())); } /** @@ -355,10 +386,9 @@ /** * Add or overwrite an existing symbol in the block * - * @param lc get lexical context * @param symbol symbol */ - public void putSymbol(final LexicalContext lc, final Symbol symbol) { + public void putSymbol(final Symbol symbol) { symbols.put(symbol.getName(), symbol); } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Tue Sep 08 15:39:51 2015 -0700 @@ -43,7 +43,7 @@ private final JoinPredecessorExpression modify; /** Iterator symbol. */ - private Symbol iterator; + private final Symbol iterator; /** Is this a normal for in loop? */ public static final int IS_FOR_IN = 1 << 0; @@ -86,23 +86,23 @@ this.flags = flags; this.init = init; this.modify = modify; + this.iterator = null; } private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test, - final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) { + final Block body, final JoinPredecessorExpression modify, final int flags, + final boolean controlFlowEscapes, final LocalVariableConversion conversion, final Symbol iterator) { super(forNode, test, body, controlFlowEscapes, conversion); this.init = init; this.modify = modify; this.flags = flags; - // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally - // is executed. - this.iterator = forNode.iterator; + this.iterator = iterator; } @Override public Node ensureUniqueLabels(final LexicalContext lc) { - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override @@ -175,7 +175,7 @@ if (this.init == init) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } /** @@ -204,10 +204,15 @@ /** * Assign an iterator symbol to this ForNode. Used for for in and for each constructs + * @param lc the current lexical context * @param iterator the iterator symbol + * @return a ForNode with the iterator set */ - public void setIterator(final Symbol iterator) { - this.iterator = iterator; + public ForNode setIterator(final LexicalContext lc, final Symbol iterator) { + if (this.iterator == iterator) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } /** @@ -228,7 +233,7 @@ if (this.modify == modify) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override @@ -236,7 +241,7 @@ if (this.test == test) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override @@ -249,7 +254,7 @@ if (this.body == body) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override @@ -257,12 +262,12 @@ if (this.controlFlowEscapes == controlFlowEscapes) { return this; } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); + return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator)); } @Override diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Tue Sep 08 15:39:51 2015 -0700 @@ -264,6 +264,11 @@ */ public static final int NEEDS_CALLEE = 1 << 26; + /** + * Is the function node cached? + */ + public static final int IS_CACHED = 1 << 27; + /** extension callsite flags mask */ public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | @@ -353,7 +358,7 @@ final List parameters, final int thisProperties, final Class rootClass, - final Source source, Namespace namespace) { + final Source source, final Namespace namespace) { super(functionNode); this.endParserState = endParserState; @@ -757,7 +762,7 @@ */ public boolean needsCallee() { // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units. - return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall(); + return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization(); } /** @@ -774,7 +779,7 @@ * Return true if function contains an apply to call transform * @return true if this function has transformed apply to call */ - public boolean hasOptimisticApplyToCall() { + public boolean hasApplyToCallSpecialization() { return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION); } @@ -1026,6 +1031,14 @@ } /** + * Return the number of parameters to this function + * @return the number of parameters + */ + public int getNumOfParams() { + return parameters.size(); + } + + /** * Returns the identifier for a named parameter at the specified position in this function's parameter list. * @param index the parameter's position. * @return the identifier for the requested named parameter. @@ -1162,6 +1175,24 @@ } /** + * Returns true if this function node has been cached. + * @return true if this function node has been cached. + */ + public boolean isCached() { + return getFlag(IS_CACHED); + } + + /** + * Mark this function node as having been cached. + * @param lc the current lexical context + * @return a function node equivalent to this one, with the flag set. + */ + public FunctionNode setCached(final LexicalContext lc) { + return setFlag(lc, IS_CACHED); + } + + + /** * Get the compile unit used to compile this function * @see Compiler * @return the compile unit diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SwitchNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SwitchNode.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SwitchNode.java Tue Sep 08 15:39:51 2015 -0700 @@ -53,7 +53,7 @@ private final boolean uniqueInteger; /** Tag symbol. */ - private Symbol tag; + private final Symbol tag; /** * Constructor @@ -71,15 +71,16 @@ this.cases = cases; this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase); this.uniqueInteger = false; + this.tag = null; } private SwitchNode(final SwitchNode switchNode, final Expression expression, final List cases, - final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) { + final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger, final Symbol tag) { super(switchNode, conversion); this.expression = expression; this.cases = cases; this.defaultCaseIndex = defaultCaseIndex; - this.tag = switchNode.getTag(); //TODO are symbols inherited as references? + this.tag = tag; this.uniqueInteger = uniqueInteger; } @@ -89,7 +90,7 @@ for (final CaseNode caseNode : cases) { newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion())); } - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger)); + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger, tag)); } @Override @@ -157,7 +158,7 @@ if (this.cases == cases) { return this; } - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); } /** @@ -189,7 +190,7 @@ if (this.expression == expression) { return this; } - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); } /** @@ -204,10 +205,15 @@ /** * Set the tag symbol for this switch. The tag symbol is where * the switch expression result is stored + * @param lc lexical context * @param tag a symbol + * @return a switch node with the symbol set */ - public void setTag(final Symbol tag) { - this.tag = tag; + public SwitchNode setTag(final LexicalContext lc, final Symbol tag) { + if (this.tag == tag) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); } /** @@ -229,12 +235,12 @@ if(this.uniqueInteger == uniqueInteger) { return this; } - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); } @Override JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { - return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger)); + return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag)); } } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Tue Sep 08 15:39:51 2015 -0700 @@ -25,7 +25,10 @@ package jdk.nashorn.internal.ir; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.PrintWriter; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; @@ -47,7 +50,9 @@ * refer to their location. */ -public final class Symbol implements Comparable { +public final class Symbol implements Comparable, Cloneable, Serializable { + private static final long serialVersionUID = 1L; + /** Is this Global */ public static final int IS_GLOBAL = 1; /** Is this a variable */ @@ -94,10 +99,10 @@ /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable * is not stored in local variable slots or it is not yet known. */ - private int firstSlot = -1; + private transient int firstSlot = -1; /** Field number in scope or property; array index in varargs when not using arguments object. */ - private int fieldIndex = -1; + private transient int fieldIndex = -1; /** Number of times this symbol is used in code */ private int useCount; @@ -144,6 +149,15 @@ } } + @Override + public Symbol clone() { + try { + return (Symbol)super.clone(); + } catch (final CloneNotSupportedException e) { + throw new AssertionError(e); + } + } + private static String align(final String string, final int max) { final StringBuilder sb = new StringBuilder(); sb.append(string.substring(0, Math.min(string.length(), max))); @@ -337,7 +351,7 @@ * Flag this symbol as scope as described in {@link Symbol#isScope()} * @return the symbol */ - public Symbol setIsScope() { + public Symbol setIsScope() { if (!isScope()) { if(shouldTrace()) { trace("SET IS SCOPE"); @@ -609,11 +623,11 @@ /** * Increase the symbol's use count by one. - * @return the symbol */ - public Symbol increaseUseCount() { - useCount++; - return this; + public void increaseUseCount() { + if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols + useCount++; + } } /** @@ -669,4 +683,10 @@ new Throwable().printStackTrace(Context.getCurrentErr()); } } + + private void readObject(final ObjectInputStream in) throws ClassNotFoundException, IOException { + in.defaultReadObject(); + firstSlot = -1; + fieldIndex = -1; + } } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Tue Sep 08 15:39:51 2015 -0700 @@ -65,7 +65,7 @@ private final List inlinedFinallies; /** Exception symbol. */ - private Symbol exception; + private final Symbol exception; private final LocalVariableConversion conversion; @@ -86,22 +86,23 @@ this.finallyBody = finallyBody; this.conversion = null; this.inlinedFinallies = Collections.emptyList(); + this.exception = null; } - private TryNode(final TryNode tryNode, final Block body, final List catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List inlinedFinallies) { + private TryNode(final TryNode tryNode, final Block body, final List catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List inlinedFinallies, final Symbol exception) { super(tryNode); this.body = body; this.catchBlocks = catchBlocks; this.finallyBody = finallyBody; this.conversion = conversion; this.inlinedFinallies = inlinedFinallies; - this.exception = tryNode.exception; + this.exception = exception; } @Override public Node ensureUniqueLabels(final LexicalContext lc) { //try nodes are never in lex context - return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies); + return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception); } @Override @@ -160,7 +161,7 @@ if (this.body == body) { return this; } - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); } /** @@ -197,7 +198,7 @@ if (this.catchBlocks == catchBlocks) { return this; } - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); } /** @@ -209,12 +210,15 @@ } /** * Set the exception symbol for this try block + * @param lc lexical context * @param exception a symbol for the compiler to store the exception in * @return new TryNode or same if unchanged */ - public TryNode setException(final Symbol exception) { - this.exception = exception; - return this; + public TryNode setException(final LexicalContext lc, final Symbol exception) { + if (this.exception == exception) { + return this; + } + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); } /** @@ -277,7 +281,7 @@ if (this.finallyBody == finallyBody) { return this; } - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); } /** @@ -293,7 +297,7 @@ return this; } assert checkInlinedFinallies(inlinedFinallies); - return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies)); + return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception)); } private static boolean checkInlinedFinallies(final List inlinedFinallies) { @@ -314,7 +318,7 @@ if(this.conversion == conversion) { return this; } - return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies); + return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception); } @Override diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Tue Sep 08 15:39:51 2015 -0700 @@ -2419,7 +2419,7 @@ } private void initScripting(final ScriptEnvironment scriptEnv) { - Object value; + ScriptObject value; value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); @@ -2428,11 +2428,13 @@ final String execName = ScriptingFunctions.EXEC_NAME; value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); + value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false); + addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); // Nashorn extension: global.echo (scripting-mode-only) // alias for "print" - value = get("print"); + value = (ScriptObject)get("print"); addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); // Nashorn extension: global.$OPTIONS (scripting-mode-only) diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,6 +26,7 @@ package jdk.nashorn.internal.parser; import static jdk.nashorn.internal.parser.TokenType.ADD; +import static jdk.nashorn.internal.parser.TokenType.BINARY_NUMBER; import static jdk.nashorn.internal.parser.TokenType.COMMENT; import static jdk.nashorn.internal.parser.TokenType.DECIMAL; import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT; @@ -40,6 +41,7 @@ import static jdk.nashorn.internal.parser.TokenType.LBRACE; import static jdk.nashorn.internal.parser.TokenType.LPAREN; import static jdk.nashorn.internal.parser.TokenType.OCTAL; +import static jdk.nashorn.internal.parser.TokenType.OCTAL_LEGACY; import static jdk.nashorn.internal.parser.TokenType.RBRACE; import static jdk.nashorn.internal.parser.TokenType.REGEX; import static jdk.nashorn.internal.parser.TokenType.RPAREN; @@ -47,6 +49,7 @@ import static jdk.nashorn.internal.parser.TokenType.XML; import java.io.Serializable; + import jdk.nashorn.internal.runtime.ECMAErrors; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.JSErrorType; @@ -75,6 +78,9 @@ /** True if here and edit strings are supported. */ private final boolean scripting; + /** True if parsing in ECMAScript 6 mode. */ + private final boolean es6; + /** True if a nested scan. (scan to completion, no EOF.) */ private final boolean nested; @@ -173,7 +179,7 @@ * @param stream the token stream to lex */ public Lexer(final Source source, final TokenStream stream) { - this(source, stream, false); + this(source, stream, false, false); } /** @@ -182,9 +188,10 @@ * @param source the source * @param stream the token stream to lex * @param scripting are we in scripting mode + * @param es6 are we in ECMAScript 6 mode */ - public Lexer(final Source source, final TokenStream stream, final boolean scripting) { - this(source, 0, source.getLength(), stream, scripting, false); + public Lexer(final Source source, final TokenStream stream, final boolean scripting, final boolean es6) { + this(source, 0, source.getLength(), stream, scripting, es6, false); } /** @@ -195,16 +202,18 @@ * @param len length of source segment to lex * @param stream token stream to lex * @param scripting are we in scripting mode + * @param es6 are we in ECMAScript 6 mode * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a * function body. This is used with the feature where the parser is skipping nested function bodies to * avoid reading ahead unnecessarily when we skip the function bodies. */ - public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) { + public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean es6, final boolean pauseOnFunctionBody) { super(source.getContent(), 1, start, len); this.source = source; this.stream = stream; this.scripting = scripting; + this.es6 = es6; this.nested = false; this.pendingLine = 1; this.last = EOL; @@ -218,6 +227,7 @@ source = lexer.source; stream = lexer.stream; scripting = lexer.scripting; + es6 = lexer.es6; nested = true; pendingLine = state.pendingLine; @@ -1088,6 +1098,24 @@ } type = HEXADECIMAL; + } else if (digit == 0 && es6 && (ch1 == 'o' || ch1 == 'O') && convertDigit(ch2, 8) != -1) { + // Skip over 0oN. + skip(3); + // Skip over remaining digits. + while (convertDigit(ch0, 8) != -1) { + skip(1); + } + + type = OCTAL; + } else if (digit == 0 && es6 && (ch1 == 'b' || ch1 == 'B') && convertDigit(ch2, 2) != -1) { + // Skip over 0bN. + skip(3); + // Skip over remaining digits. + while (convertDigit(ch0, 2) != -1) { + skip(1); + } + + type = BINARY_NUMBER; } else { // Check for possible octal constant. boolean octal = digit == 0; @@ -1105,7 +1133,7 @@ } if (octal && position - start > 1) { - type = OCTAL; + type = OCTAL_LEGACY; } else if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') { // Must be a double. if (ch0 == '.') { @@ -1637,10 +1665,14 @@ switch (Token.descType(token)) { case DECIMAL: return Lexer.valueOf(source.getString(start, len), 10); // number - case OCTAL: - return Lexer.valueOf(source.getString(start, len), 8); // number case HEXADECIMAL: return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number + case OCTAL_LEGACY: + return Lexer.valueOf(source.getString(start, len), 8); // number + case OCTAL: + return Lexer.valueOf(source.getString(start + 2, len - 2), 8); // number + case BINARY_NUMBER: + return Lexer.valueOf(source.getString(start + 2, len - 2), 2); // number case FLOATING: final String str = source.getString(start, len); final double value = Double.valueOf(str); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Tue Sep 08 15:39:51 2015 -0700 @@ -273,7 +273,7 @@ try { stream = new TokenStream(); - lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null); + lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null); lexer.line = lexer.pendingLine = lineOffset + 1; line = lineOffset; @@ -309,7 +309,7 @@ public List parseFormalParameterList() { try { stream = new TokenStream(); - lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions); + lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); // Set up first token (skips opening EOL.) k = -1; @@ -333,7 +333,7 @@ public FunctionNode parseFunctionBody() { try { stream = new TokenStream(); - lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions); + lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); final int functionLine = line; // Set up first token (skips opening EOL.) @@ -716,7 +716,7 @@ restoreBlock(body); body.setFlag(Block.NEEDS_SCOPE); - final Block programBody = new Block(functionToken, functionLine, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements()); + final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements()); lc.pop(script); script.setLastToken(token); @@ -1216,11 +1216,10 @@ final long forToken = token; final int forLine = line; // start position of this for statement. This is used - // for sort order for variables declared in the initialzer + // for sort order for variables declared in the initializer // part of this 'for' statement (if any). final int forStart = Token.descPosition(forToken); // When ES6 for-let is enabled we create a container block to capture the LET. - final int startLine = start; final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; // Create FOR node, capturing FOR token. @@ -1341,22 +1340,24 @@ body = getStatement(); } finally { lc.pop(forNode); - } - - if (vars != null) { - for (final VarNode var : vars) { - appendStatement(var); + + if (vars != null) { + for (final VarNode var : vars) { + appendStatement(var); + } + } + if (body != null) { + appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify)); } - } - if (body != null) { - appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify)); - } - if (outer != null) { - restoreBlock(outer); - appendStatement(new BlockStatement(startLine, new Block( - outer.getToken(), - body.getFinish(), - outer.getStatements()))); + if (outer != null) { + restoreBlock(outer); + if (body != null) { + appendStatement(new BlockStatement(forLine, new Block( + outer.getToken(), + body.getFinish(), + outer.getStatements()))); + } + } } } @@ -1954,7 +1955,7 @@ } detectSpecialProperty(ident); return ident; - case OCTAL: + case OCTAL_LEGACY: if (isStrictMode) { throw error(AbstractParser.message("strict.no.octal"), token); } @@ -1962,6 +1963,8 @@ case ESCSTRING: case DECIMAL: case HEXADECIMAL: + case OCTAL: + case BINARY_NUMBER: case FLOATING: case REGEX: case XML: @@ -2053,13 +2056,13 @@ // LBRACKET tested in caller. next(); - // Prepare to accummulating elements. + // Prepare to accumulate elements. final List elements = new ArrayList<>(); // Track elisions. boolean elision = true; loop: while (true) { - switch (type) { + switch (type) { case RBRACKET: next(); @@ -2223,7 +2226,7 @@ switch (type) { case IDENT: return getIdent().setIsPropertyName(); - case OCTAL: + case OCTAL_LEGACY: if (isStrictMode) { throw error(AbstractParser.message("strict.no.octal"), token); } @@ -2231,6 +2234,8 @@ case ESCSTRING: case DECIMAL: case HEXADECIMAL: + case OCTAL: + case BINARY_NUMBER: case FLOATING: return getLiteral(); default: @@ -2284,7 +2289,7 @@ } } - propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); + propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); } else { propertyName = propertyName(); } @@ -2553,7 +2558,7 @@ final long callToken = token; switch (type) { - case LBRACKET: + case LBRACKET: { next(); // Get array index. @@ -2565,8 +2570,8 @@ lhs = new IndexNode(callToken, finish, lhs, index); break; - - case PERIOD: + } + case PERIOD: { if (lhs == null) { throw error(AbstractParser.message("expected.operand", type.getNameOrType())); } @@ -2579,7 +2584,7 @@ lhs = new AccessNode(callToken, finish, lhs, property.getName()); break; - + } default: break loop; } @@ -3034,7 +3039,7 @@ assert parserState != null; stream.reset(); - lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions); + lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6); line = parserState.line; linePosition = parserState.linePosition; // Doesn't really matter, but it's safe to treat it as if there were a semicolon before @@ -3063,8 +3068,8 @@ this.linePosition = linePosition; } - Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) { - final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true); + Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) { + final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true); newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON)); return newLexer; } @@ -3107,15 +3112,6 @@ return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); } - /* - * parse LHS [a, b, ..., c]. - * - * JavaScript 1.8. - */ - //private Node destructureExpression() { - // return null; - //} - /** * PostfixExpression : * LeftHandSideExpression @@ -3127,7 +3123,7 @@ * UnaryExpression : * PostfixExpression * delete UnaryExpression - * Node UnaryExpression + * void UnaryExpression * typeof UnaryExpression * ++ UnaryExpression * -- UnaryExpression @@ -3333,7 +3329,6 @@ // This method is protected so that subclass can get details // at expression start point! - // TODO - Destructuring array. // Include commas in expression parsing. return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false); } @@ -3407,7 +3402,6 @@ // This method is protected so that subclass can get details // at assignment expression start point! - // TODO - Handle decompose. // Exclude commas in expression parsing. return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Tue Sep 08 15:39:51 2015 -0700 @@ -170,8 +170,10 @@ YIELD (FUTURESTRICT, "yield"), DECIMAL (LITERAL, null), + HEXADECIMAL (LITERAL, null), + OCTAL_LEGACY (LITERAL, null), OCTAL (LITERAL, null), - HEXADECIMAL (LITERAL, null), + BINARY_NUMBER (LITERAL, null), FLOATING (LITERAL, null), STRING (LITERAL, null), ESCSTRING (LITERAL, null), diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstSerializer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstSerializer.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.nashorn.internal.runtime; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.runtime.options.Options; + +/** + * This static utility class performs serialization of FunctionNode ASTs to a byte array. + * The format is a standard Java serialization stream, deflated. + */ +final class AstSerializer { + // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed + // and size. + private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4); + static byte[] serialize(final FunctionNode fn) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final Deflater deflater = new Deflater(COMPRESSION_LEVEL); + try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) { + oout.writeObject(fn); + } catch (final IOException e) { + throw new AssertionError("Unexpected exception serializing function", e); + } finally { + deflater.end(); + } + return out.toByteArray(); + } +} diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Tue Sep 08 15:39:51 2015 -0700 @@ -27,6 +27,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; + import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -820,7 +821,7 @@ // isn't available, we'll use the old one bound into the call site. final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo; FunctionNode fn = effectiveOptInfo.reparse(); - final boolean serialized = effectiveOptInfo.isSerialized(); + final boolean cached = fn.isCached(); final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of if (!shouldRecompile) { @@ -828,11 +829,11 @@ // recompiled a deoptimized version for an inner invocation. // We still need to do the rest of from the beginning logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); - return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null); + return restOfHandle(effectiveOptInfo, compiler.compile(fn, cached ? CompilationPhases.COMPILE_CACHED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null); } logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); - fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE); + fn = compiler.compile(fn, cached ? CompilationPhases.RECOMPILE_CACHED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE); log.fine("Reusable IR generated"); // compile the rest of the function, and install it @@ -956,10 +957,6 @@ FunctionNode reparse() { return data.reparse(); } - - boolean isSerialized() { - return data.isSerialized(); - } } @SuppressWarnings("unused") diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,16 +26,24 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.lookup.Lookup.MH; + import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import jdk.internal.dynalink.support.NameCodec; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; @@ -45,8 +53,15 @@ import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; import jdk.nashorn.internal.codegen.TypeMap; import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.Block; +import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.LexicalContext; +import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.SwitchNode; +import jdk.nashorn.internal.ir.Symbol; +import jdk.nashorn.internal.ir.TryNode; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.parser.Parser; @@ -55,6 +70,7 @@ import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; +import jdk.nashorn.internal.runtime.options.Options; /** * This is a subclass that represents a script function that may be regenerated, * for example with specialization based on call site types, or lazily generated. @@ -66,6 +82,8 @@ /** Prefix used for all recompiled script classes */ public static final String RECOMPILATION_PREFIX = "Recompilation$"; + private static final ExecutorService astSerializerExecutorService = createAstSerializerExecutorService(); + /** Unique function node id for this function node */ private final int functionNodeId; @@ -77,8 +95,12 @@ /** Source from which FunctionNode was parsed. */ private transient Source source; - /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */ - private final byte[] serializedAst; + /** + * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be + * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe + * to be cleared as they can be reparsed). + */ + private volatile Object cachedAst; /** Token of this function within the source. */ private final long token; @@ -128,7 +150,6 @@ * @param nestedFunctions nested function map * @param externalScopeDepths external scope depths * @param internalSymbols internal symbols to method, defined in its scope - * @param serializedAst a serialized AST representation. Normally only used for split functions. */ public RecompilableScriptFunctionData( final FunctionNode functionNode, @@ -136,8 +157,7 @@ final AllocationStrategy allocationStrategy, final Map nestedFunctions, final Map externalScopeDepths, - final Set internalSymbols, - final byte[] serializedAst) { + final Set internalSymbols) { super(functionName(functionNode), Math.min(functionNode.getParameters().size(), MAX_ARITY), @@ -161,7 +181,6 @@ nfn.setParent(this); } - this.serializedAst = serializedAst; createLogger(); } @@ -244,7 +263,7 @@ * @return parent data, or null if non exists and also null IF UNKNOWN. */ public RecompilableScriptFunctionData getParent() { - return parent; + return parent; } void setParent(final RecompilableScriptFunctionData parent) { @@ -358,13 +377,11 @@ return allocationStrategy.allocate(map); } - boolean isSerialized() { - return serializedAst != null; - } - FunctionNode reparse() { - if (isSerialized()) { - return deserialize(); + final FunctionNode cachedFunction = getCachedAst(); + if (cachedFunction != null) { + assert cachedFunction.isCached(); + return cachedFunction; } final int descPosition = Token.descPosition(token); @@ -391,7 +408,98 @@ return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName); } - private FunctionNode deserialize() { + private FunctionNode getCachedAst() { + final Object lCachedAst = cachedAst; + // Are we softly caching the AST? + if (lCachedAst instanceof Reference) { + final FunctionNode fn = (FunctionNode)((Reference)lCachedAst).get(); + if (fn != null) { + // Yes we are - this is fast + return cloneSymbols(fn); + } + // Are we strongly caching a serialized AST (for split functions only)? + } else if (lCachedAst instanceof SerializedAst) { + final SerializedAst serializedAst = (SerializedAst)lCachedAst; + // Even so, are we also softly caching the AST? + final FunctionNode cachedFn = serializedAst.cachedAst.get(); + if (cachedFn != null) { + // Yes we are - this is fast + return cloneSymbols(cachedFn); + } + final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst); + // Softly cache after deserialization, maybe next time we won't need to deserialize + serializedAst.cachedAst = new SoftReference<>(deserializedFn); + return deserializedFn; + } + // No cached representation; return null for reparsing + return null; + } + + /** + * Sets the AST to cache in this function + * @param astToCache the new AST to cache + */ + public void setCachedAst(final FunctionNode astToCache) { + assert astToCache.getId() == functionNodeId; // same function + assert !(cachedAst instanceof SerializedAst); // Can't overwrite serialized AST + + final boolean isSplit = astToCache.isSplit(); + // If we're caching a split function, we're doing it in the eager pass, hence there can be no other + // cached representation already. In other words, isSplit implies cachedAst == null. + assert !isSplit || cachedAst == null; // + + final FunctionNode symbolClonedAst = cloneSymbols(astToCache); + final Reference ref = new SoftReference<>(symbolClonedAst); + cachedAst = ref; + + // Asynchronously serialize split functions. + if (isSplit) { + astSerializerExecutorService.execute(() -> { + cachedAst = new SerializedAst(symbolClonedAst, ref); + }); + } + } + + /** + * Creates the AST serializer executor service used for in-memory serialization of split functions' ASTs. + * It is created with an unbounded queue (so it can queue any number of pending tasks). Its core and max + * threads is the same, but they are all allowed to time out so when there's no work, they can all go + * away. The threads will be daemons, and they will time out if idle for a minute. Their priority is also + * slightly lower than normal priority as we'd prefer the CPU to keep running the program; serializing + * split function is a memory conservation measure (it allows us to release the AST), it can wait a bit. + * @return an executor service with above described characteristics. + */ + private static ExecutorService createAstSerializerExecutorService() { + final int threads = Math.max(1, Options.getIntProperty("nashorn.serialize.threads", Runtime.getRuntime().availableProcessors() / 2)); + final ThreadPoolExecutor service = new ThreadPoolExecutor(threads, threads, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>(), + (r) -> { + final Thread t = new Thread(r, "Nashorn AST Serializer"); + t.setDaemon(true); + t.setPriority(Thread.NORM_PRIORITY - 1); + return t; + }); + service.allowCoreThreadTimeOut(true); + return service; + } + + /** + * A tuple of a serialized AST and a soft reference to a deserialized AST. This is used to cache split + * functions. Since split functions are altered from their source form, they can't be reparsed from + * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst} + * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on + * deserialization costs. + */ + private static class SerializedAst { + private final byte[] serializedAst; + private volatile Reference cachedAst; + + SerializedAst(final FunctionNode fn, final Reference cachedAst) { + this.serializedAst = AstSerializer.serialize(fn); + this.cachedAst = cachedAst; + } + } + + private FunctionNode deserialize(final byte[] serializedAst) { final ScriptEnvironment env = installer.getOwner(); final Timing timing = env._timing; final long t1 = System.nanoTime(); @@ -402,6 +510,107 @@ } } + private FunctionNode cloneSymbols(final FunctionNode fn) { + final IdentityHashMap symbolReplacements = new IdentityHashMap<>(); + final boolean cached = fn.isCached(); + // blockDefinedSymbols is used to re-mark symbols defined outside the function as global. We only + // need to do this when we cache an eagerly parsed function (which currently means a split one, as we + // don't cache non-split functions from the eager pass); those already cached, or those not split + // don't need this step. + final Set blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<>()) : null; + FunctionNode newFn = (FunctionNode)fn.accept(new NodeVisitor(new LexicalContext()) { + + private Symbol getReplacement(final Symbol original) { + if (original == null) { + return null; + } + final Symbol existingReplacement = symbolReplacements.get(original); + if (existingReplacement != null) { + return existingReplacement; + } + final Symbol newReplacement = original.clone(); + symbolReplacements.put(original, newReplacement); + return newReplacement; + } + + @Override + public Node leaveIdentNode(final IdentNode identNode) { + final Symbol oldSymbol = identNode.getSymbol(); + if (oldSymbol != null) { + final Symbol replacement = getReplacement(oldSymbol); + return identNode.setSymbol(replacement); + } + return identNode; + } + + @Override + public Node leaveForNode(final ForNode forNode) { + return ensureUniqueLabels(forNode.setIterator(lc, getReplacement(forNode.getIterator()))); + } + + @Override + public Node leaveSwitchNode(final SwitchNode switchNode) { + return ensureUniqueLabels(switchNode.setTag(lc, getReplacement(switchNode.getTag()))); + } + + @Override + public Node leaveTryNode(final TryNode tryNode) { + return ensureUniqueLabels(tryNode.setException(lc, getReplacement(tryNode.getException()))); + } + + @Override + public boolean enterBlock(final Block block) { + for(final Symbol symbol: block.getSymbols()) { + final Symbol replacement = getReplacement(symbol); + if (blockDefinedSymbols != null) { + blockDefinedSymbols.add(replacement); + } + } + return true; + } + + @Override + public Node leaveBlock(final Block block) { + return ensureUniqueLabels(block.replaceSymbols(lc, symbolReplacements)); + } + + @Override + public Node leaveFunctionNode(final FunctionNode functionNode) { + return functionNode.setParameters(lc, functionNode.visitParameters(this)); + } + + @Override + protected Node leaveDefault(final Node node) { + return ensureUniqueLabels(node); + }; + + private Node ensureUniqueLabels(final Node node) { + // If we're returning a cached AST, we must also ensure unique labels + return cached ? node.ensureUniqueLabels(lc) : node; + } + }); + + if (blockDefinedSymbols != null) { + // Mark all symbols not defined in blocks as globals + Block newBody = null; + for(final Symbol symbol: symbolReplacements.values()) { + if(!blockDefinedSymbols.contains(symbol)) { + assert symbol.isScope(); // must be scope + assert externalScopeDepths.containsKey(symbol.getName()); // must be known to us as an external + // Register it in the function body symbol table as a new global symbol + symbol.setFlags((symbol.getFlags() & ~Symbol.KINDMASK) | Symbol.IS_GLOBAL); + if (newBody == null) { + newBody = newFn.getBody().copyWithNewSymbols(); + newFn = newFn.setBody(null, newBody); + } + assert newBody.getExistingSymbol(symbol.getName()) == null; // must not be defined in the body already + newBody.putSymbol(symbol); + } + } + } + return newFn.setCached(null); + } + private boolean getFunctionFlag(final int flag) { return (functionFlags & flag) != 0; } @@ -512,9 +721,9 @@ final FunctionNode fn = reparse(); final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope); final FunctionNode compiledFn = compiler.compile(fn, - isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL); + fn.isCached() ? CompilationPhases.COMPILE_ALL_CACHED : CompilationPhases.COMPILE_ALL); - if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) { + if (persist && !compiledFn.hasApplyToCallSpecialization()) { compiler.persistClassInfo(cacheKey, compiledFn); } return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints()); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Tue Sep 08 15:39:51 2015 -0700 @@ -26,6 +26,7 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; @@ -70,6 +71,9 @@ /** EXIT name - special property used by $EXEC API. */ public static final String EXIT_NAME = "$EXIT"; + /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */ + public static final String THROW_ON_ERROR_NAME = "throwOnError"; + /** Names of special properties used by $ENV API. */ public static final String ENV_NAME = "$ENV"; @@ -247,6 +251,19 @@ } } + // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not + if (exit != 0) { + // get the $EXEC function object from the global object + final Object exec = global.get(EXEC_NAME); + assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!"; + + // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError + // If that property is not set or set to false, then silently proceed with the rest. + if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) { + throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit)); + } + } + // Return the result from stdout. return out; } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java Tue Sep 01 12:57:41 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.runtime.arrays; - -/** - * Mechanism for communicating that something isn't a plain - * numeric integer array index. This enables things like - * array getters for the fast case in a try, basically - * just consisting of an "array[index]" access without - * any checks of boundary conditions that rarely happen - */ -@SuppressWarnings("serial") -class InvalidArrayIndexException extends Exception { - - private final Object index; - - InvalidArrayIndexException(final Object index) { - super(index == null ? "null" : index.toString()); - this.index = index; - } - - InvalidArrayIndexException(final int index) { - this(Integer.valueOf(index)); - } - - InvalidArrayIndexException(final long index) { - this(Long.valueOf(index)); - } - - InvalidArrayIndexException(final double index) { - this(Double.valueOf(index)); - } - - @Override - public String toString() { - return index.toString(); - } - - Object getIndex() { - return index; - } - -} diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/AdaptationException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/AdaptationException.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/AdaptationException.java Tue Sep 08 15:39:51 2015 -0700 @@ -30,6 +30,7 @@ private final AdaptationResult adaptationResult; AdaptationException(final AdaptationResult.Outcome outcome, final String classList) { + super(null, null, false, false); this.adaptationResult = new AdaptationResult(outcome, classList); } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Sep 08 15:39:51 2015 -0700 @@ -189,7 +189,7 @@ * @return true if the obj is an instance of @FunctionalInterface interface */ public static boolean isFunctionalInterfaceObject(final Object obj) { - return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null); + return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null); } /** diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Tue Sep 08 15:39:51 2015 -0700 @@ -79,10 +79,10 @@ } // cache of @FunctionalInterface method of implementor classes - private static final ClassValue FUNCTIONAL_IFACE_METHOD = new ClassValue() { + private static final ClassValue FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue() { @Override - protected Method computeValue(final Class type) { - return findFunctionalInterfaceMethod(type); + protected String computeValue(final Class type) { + return findFunctionalInterfaceMethodName(type); } }; @@ -107,19 +107,21 @@ // annotated interface. This way Java method, constructor references or // implementations of java.util.function.* interfaces can be called as though // those are script functions. - final Method m = getFunctionalInterfaceMethod(self.getClass()); - if (m != null) { + final String name = getFunctionalInterfaceMethodName(self.getClass()); + if (name != null) { final MethodType callType = desc.getMethodType(); - // 'callee' and 'thiz' passed from script + actual arguments - if (callType.parameterCount() != m.getParameterCount() + 2) { - throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self)); - } - return new GuardedInvocation( - // drop 'thiz' passed from the script. - MH.dropArguments(linkerServices.filterInternalObjects(desc.getLookup().unreflect(m)), 1, - callType.parameterType(1)), Guards.getInstanceOfGuard( - m.getDeclaringClass())).asTypeSafeReturn( - new NashornBeansLinkerServices(linkerServices), callType); + // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod: + final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(), + "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2), + NashornCallSiteDescriptor.getFlags(desc)); + final GuardedInvocation gi = getGuardedInvocation(beansLinker, + linkRequest.replaceArguments(newDesc, linkRequest.getArguments()), + new NashornBeansLinkerServices(linkerServices)); + + // drop 'thiz' passed from the script. + return gi.replaceMethods( + MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)), + gi.getGuard()); } } return getGuardedInvocation(beansLinker, linkRequest, linkerServices); @@ -163,7 +165,7 @@ return arg instanceof ConsString ? arg.toString() : arg; } - private static Method findFunctionalInterfaceMethod(final Class clazz) { + private static String findFunctionalInterfaceMethodName(final Class clazz) { if (clazz == null) { return null; } @@ -179,20 +181,20 @@ // return the first abstract method for (final Method m : iface.getMethods()) { if (Modifier.isAbstract(m.getModifiers())) { - return m; + return m.getName(); } } } } // did not find here, try super class - return findFunctionalInterfaceMethod(clazz.getSuperclass()); + return findFunctionalInterfaceMethodName(clazz.getSuperclass()); } // Returns @FunctionalInterface annotated interface's single abstract - // method. If not found, returns null. - static Method getFunctionalInterfaceMethod(final Class clazz) { - return FUNCTIONAL_IFACE_METHOD.get(clazz); + // method name. If not found, returns null. + static String getFunctionalInterfaceMethodName(final Class clazz) { + return FUNCTIONAL_IFACE_METHOD_NAME.get(clazz); } static MethodHandleTransformer createHiddenObjectFilter() { diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Tue Sep 08 15:39:51 2015 -0700 @@ -24,6 +24,6 @@ private static final long serialVersionUID = -6027192180014164667L; public JOniException(final String message) { - super(message); + super(message, null, false, false); } } diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Tue Sep 08 15:39:51 2015 -0700 @@ -163,6 +163,7 @@ range.error.invalid.date=Invalid Date range.error.too.many.errors=Script contains too many errors: {0} errors range.error.concat.string.too.big=Concatenated String is too big +range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0} reference.error.not.defined="{0}" is not defined reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8043232.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -1,14 +1,28 @@ bcd -[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] +[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] red TypeError: No such Java class: java.lang.NonExistent TypeError: No such Java constructor: Object(String) TypeError: Java constructor signature invalid: Object()xxxxx TypeError: Java constructor signature invalid: Object( TypeError: Java constructor signature invalid: Object) -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor. -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor. -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new". +TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod + String java.lang.System.getProperty(String,String) + String java.lang.System.getProperty(String) +] cannot be used as a constructor. +TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod + void java.io.PrintStream.println() + void java.io.PrintStream.println(boolean) + void java.io.PrintStream.println(char) + void java.io.PrintStream.println(char[]) + void java.io.PrintStream.println(double) + void java.io.PrintStream.println(float) + void java.io.PrintStream.println(int) + void java.io.PrintStream.println(long) + void java.io.PrintStream.println(Object) + void java.io.PrintStream.println(String) +] cannot be used as a constructor. +TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". TypeError: No such Java constructor: Runnable() TypeError: No such Java constructor: Runnable(int) java.lang.InstantiationException: java.io.InputStream diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8049242.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -1,10 +1,10 @@ abc -[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] +[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] ava TypeError: null is not a function TypeError: null is not a function TypeError: null is not a function -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new". +TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". TypeError: null is not a function TypeError: null is not a function java.lang.InstantiationException: java.io.InputStream diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8068901.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8068901.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8068901: Surprising behavior with more than one functional interface on a class + * + * @test + * @run + */ + +var Consumer = java.util.function.Consumer; +var JFunction = java.util.function.Function; + +var fc = new (Java.extend(JFunction, Consumer))({ + apply: function(x) { print("fc invoked as a function") }, + accept: function(x) { print("fc invoked as a consumer") } +}); + +var c = new Consumer(function(x) { print("c invoked as a consumer") }); + +var cf = new (Java.extend(Consumer, JFunction))({ + apply: function(x) { print("cf invoked as a function") }, + accept: function(x) { print("cf invoked as a consumer") } +}); + +var f = new JFunction(function(x) { print("f invoked as a function") }); + +for each(x in [fc, c, fc, cf, f, cf, c, fc, f, cf]) { x(null); } + diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8068901.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8068901.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,10 @@ +fc invoked as a function +c invoked as a consumer +fc invoked as a function +cf invoked as a consumer +f invoked as a function +cf invoked as a consumer +c invoked as a consumer +fc invoked as a function +f invoked as a function +cf invoked as a consumer diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8068903.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8068903.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8068903: Can't invoke vararg @FunctionalInterface methods + * + * @test + * @run + */ + +var vc = new (Java.type("jdk.nashorn.test.models.VarArgConsumer"))( + function(x) { + Assert.assertTrue(x.length == 3); + Assert.assertTrue(x[0] == 1); + Assert.assertTrue(x[1] == 2); + Assert.assertTrue(x[2] == 3); + } +); + +vc(1, 2, 3); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8079470.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -1,2 +1,2 @@ -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod File java.io.File.java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures. +TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. +TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures. diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8134731.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8134731.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8134731: `Function.prototype.apply` interacts incorrectly with `arguments` + * + * @test + * @run + */ + +function func() { + return (function(f){ + return function(a1, a2, a3, a4){ + return (f.apply(this, arguments)); + } + })(function(){ + return arguments.length; + }) +} + +Assert.assertTrue(func()() == 0); +Assert.assertTrue(func()(33) == 1); +Assert.assertTrue(func()(33, true) == 2); +Assert.assertTrue(func()(33, true, "hello") == 3); +Assert.assertTrue(func()(33, true, "hello", "world") == 4); +Assert.assertTrue(func()(33, true, "hello", "world", 42) == 5); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8134865.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8134865.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8134865: Need to restore for container block from lexical context in finally + * + * @test + * @option --language=es6 + */ + +try { + eval("function f() { for (x : y) { } }"); + throw "should not reach here"; +} catch (e) { + if (!(e instanceof SyntaxError)) throw e; +} diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/JDK-8134939.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8134939.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8134939: Improve toString method of Dynalink OverloadedDynamicMethod + * + * @test + * @run + */ + +var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter")); + +Assert.assertEquals(String(overloadedSetter.foo), + "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + + " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" + + " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" + + "]"); + +Assert.assertEquals(String(overloadedSetter.setColor), + "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + + " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" + + " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" + + "]"); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/basic/es6/numeric-literals.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/es6/numeric-literals.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8134873: ECMAScript 6 Numeric Literals + * + * @test + * @option --language=es6 + */ + +function assertEquals(expected, actual) { + if (expected !== actual) { + throw new Error("expected: " + expected + ", actual: " + actual); + } +} + +assertEquals(0b0, 0); +assertEquals(0B0, 0); +assertEquals(0b01, 1); +assertEquals(0B10, 2); +assertEquals(0b11111111, 255); +assertEquals(0b11111111111111111111111111111111, 4294967295); + +assertEquals(0o0, 0); +assertEquals(0O0, 0); +assertEquals(0o01, 1); +assertEquals(0O10, 8); +assertEquals(0o777, 511); + diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/trusted/JDK-8087292.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/trusted/JDK-8087292.js Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e" + * + * @test + * @option -scripting + * @run + */ + +function tryExec() { + try { + `java` + } catch (e) { + print(e); + } + + // make sure we got non-zero ("failure") exit code! + if ($EXIT == 0) { + print("Error: expected $EXIT code to be non-zero"); + } +} + +// no exception now! +tryExec(); + +// turn on error with non-zero exit code +$EXEC.throwOnError = true; +tryExec(); + +// no exception after this +$EXEC.throwOnError = false; +tryExec(); diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/trusted/JDK-8087292.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/trusted/JDK-8087292.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,1 @@ +RangeError: $EXEC returned non-zero exit code: 1 diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/script/trusted/classfilter.js.EXPECTED --- a/nashorn/test/script/trusted/classfilter.js.EXPECTED Tue Sep 01 12:57:41 2015 +0300 +++ b/nashorn/test/script/trusted/classfilter.js.EXPECTED Tue Sep 08 15:39:51 2015 -0700 @@ -4,7 +4,18 @@ typeof java.util.Map evalutes to function typeof java.util.HashMap evalutes to function var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42} -java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] +java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod + void java.io.PrintStream.println() + void java.io.PrintStream.println(boolean) + void java.io.PrintStream.println(char) + void java.io.PrintStream.println(char[]) + void java.io.PrintStream.println(double) + void java.io.PrintStream.println(float) + void java.io.PrintStream.println(int) + void java.io.PrintStream.println(long) + void java.io.PrintStream.println(Object) + void java.io.PrintStream.println(String) +] java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)] new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext diff -r 23b29549f8d1 -r 54fbe836fcf0 nashorn/test/src/jdk/nashorn/test/models/VarArgConsumer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/nashorn/test/models/VarArgConsumer.java Tue Sep 08 15:39:51 2015 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.test.models; + +/** + * Simple function interface with a varargs SAM method. + */ +@FunctionalInterface +public interface VarArgConsumer { + public void apply(Object... o); +} +