--- 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
--- 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
--- 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"`
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
-
-
--- 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) \
--- 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), \
--- 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), \
--- 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
--- 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;
--- 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;
--- 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
--- 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 @@
<a href="CLSFractal.java">The source</a>.
</body>
</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 @@
<a href="XYZApp.java">The source</a>.
</body>
</html>
-
-
-
-
-
-
--- 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());
--- 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.
+ *
+ * <p>
+ * 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.
*
* <p>
* This method traverses the list of registered security
--- 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:<libname>[=<options>]\n\
-\ load native agent library <libname>, e.g. -agentlib:hprof\n\
-\ see also, -agentlib:jdwp=help and -agentlib:hprof=help\n\
+\ load native agent library <libname>, e.g. -agentlib:jdwp\n\
+\ see also -agentlib:jdwp=help\n\
\ -agentpath:<pathname>[=<options>]\n\
\ load native agent library by full pathname\n\
\ -javaagent:<jarpath>[=<options>]\n\
--- 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;
}
-
-
--- 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));
}
--- 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
-
-
-
--- /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;
+ }});
+ }
+}
--- 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;
- }});
- }
-}
--- 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 <unistd.h>
#include <fcntl.h>
+#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"));
}
/**************************************************************
--- /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 <stdlib.h>
+#include <dlfcn.h>
+
+#ifdef __solaris__
+#include <strings.h>
+#endif
+
+#if defined(__linux__)
+#include <string.h>
+#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;
+}
--- 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 <stdlib.h>
-#include <dlfcn.h>
-
-#ifdef __solaris__
-#include <strings.h>
-#endif
-
-#if defined(__linux__)
-#include <string.h>
-#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;
-}
--- 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
-
-
--- 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
+}
--- 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
+}
--- 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;
}
}
-
-
--- 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;
}
-
-
--- 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
+}
--- 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
+}
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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;
}
-
-
--- 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];
}
-
-
--- 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);
}
-
-
--- 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;
}
-
-
--- 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
+}
--- 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();
}
-
-
--- 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.
-
-
--- 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 @@
</body>
</html>
-
-
-
-
-
--- 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 @@
* <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
*
* @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<ObjectName>, 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<String,String> _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.
+ * <p>
+ * The following masks can be used to extract the value:
+ * <ul>
+ * <li>{@linkplain ObjectName#DOMAIN_PATTERN}</li>
+ * <li>{@linkplain ObjectName#PROPLIST_PATTERN}</li>
+ * <li>{@linkplain ObjectName#PROPVAL_PATTERN}</li>
+ * <li>{@linkplain ObjectName#DOMAIN_LENGTH_MASK}</li>
+ * </ul>
+ * </p>.
*/
- 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 <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
- * values in <code>table</code> does not follow the rules for quoting.
+ * values in <code>table</code> 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<String,String> 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
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> 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
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> 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
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> 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
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> 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<String,String> 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<String,String> 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)))
--- 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.
* <P>
- * 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,
--- 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.
* <P>
- * 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):
+ * <ul>
+ * <li> <i>p</i> is an instanceof {@code ServicePermission},
+ * <li> <i>p</i>'s actions are a proper subset of this
+ * {@code ServicePermission}'s actions,
+ * <li> <i>p</i>'s name is equal to this {@code ServicePermission}'s name
+ * or this {@code ServicePermission}'s name is "*".
+ * </ul>
+ *
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
--- 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
--- 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
+}
--- 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 @@
<HTML><HEAD></HEAD><BODY><P>
algorithm factories.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:KeyValue</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:KeyInfo</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:X509Data</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
implementations for retrieval of certificates and public keys from elements.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
the resolver framework for retrieval of certificates and public keys from elements.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
implementations of resolvers for retrieval for certificates and public keys from user-specified locations.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></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 @@
<HTML><HEAD></HEAD><BODY><P>
a resolver framework for certificates and public keys from user-specified locations.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- 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
+}
--- 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;
}
--- 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 @@
<value>4</value>
</entry>
</supportedModules>
-</device>
\ No newline at end of file
+</device>
--- 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: <a href="Validator/src/">Validator/src/</a>
</ul>
</body>
-</html>
\ No newline at end of file
+</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: <a href="src/WC.java">src/WC.java</a>
</ul>
</body>
-</html>
\ No newline at end of file
+</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 @@
</ul>
</body>
-</html>
\ No newline at end of file
+</html>
--- 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
--- 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]
--- 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
-
-
--- /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();
+ }
+}
--- /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();
+ }
+}
--- /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();
+ }
+}
--- /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;
+ }
+}
--- /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;
+ }
+}
--- /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<byte[]> 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");
+ }
+ }
+}
--- /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<byte[]> 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);
+ }
+ }
+}
--- /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);
+ }
+ }
+}
--- 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
+}
--- 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 @@
}
}
}
-
-
-
--- 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"
}
-
-
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
+}
--- 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";
};
-
-
--- 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
+}
--- 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
+}
--- 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
+}
--- 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 @@
<applet CODE="MultiResolutionCursorTest.class" WIDTH=300 HEIGHT=100></applet>
<p> See the dialog box (usually in upper left corner) for instructions</p>
</body>
-</html>
\ No newline at end of file
+</html>
--- 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
+}
--- 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 @@
}
}
}
-
-
--- 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 @@
}
}
}
-
-
--- 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>(frame, que));
}
-}
\ No newline at end of file
+}
--- 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
+}
--- 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
+}
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- 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
+}
--- 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);
}
}
-
-
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
+}
--- 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 @@
<APPLET CODE="IOExceptionIfEncodedURLTest.class" WIDTH=200 HEIGHT=200></APPLET>
</body>
-</html>
\ No newline at end of file
+</html>
--- 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
+}
--- 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
--- 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
+}
--- 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 );
}
}
-
-
--- 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 @@
<APPLET CODE="bug4490692.class" WIDTH=0 HEIGHT=0></APPLET>
</body>
</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 @@
<APPLET CODE="bug4959409.class" WIDTH=0 HEIGHT=0></APPLET>
</body>
</html>
-
-
--- 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.
--- 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
+;
--- 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
-
-
-
--- 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
-
-
--- 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
-
-
--- 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
+};
--- 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
-
-
-
--- 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
-
-
--- 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;
--- 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}
-
-
--- 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
<JAVA-HOME>/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
--- 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 @@
}
}
}
-
-
--- 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(); }
}
}
-
-
--- 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
+}
--- 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 @@
-<APPLET CODE="bug4123285.class" CODEBASE="./" WIDTH="250" HEIGHT="325" ALIGN="TOP"></APPLET>
\ No newline at end of file
+<APPLET CODE="bug4123285.class" CODEBASE="./" WIDTH="250" HEIGHT="325" ALIGN="TOP"></APPLET>
--- 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
+}
--- 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
-
-
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
--- /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);
+ }
+}
--- 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
--- 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
+};
--- 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
+};
--- 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
+};
--- 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
+};
--- 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 @@
}
}
-
-
--- 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 @@
<applet width="500" height="1" code="bug8065098.class">
</applet>
</body>
-</html>
\ No newline at end of file
+</html>
--- 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
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
+}
--- 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.
-
-
--- 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
+}
--- 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
+}
--- 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
+}
--- 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
+}
--- 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(<b>true</b>);
}
-}
\ No newline at end of file
+}
--- 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
+}
--- 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);
}
}
-
-
--- 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 @@
<xs:element name="foo" type="xs:int" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
--- 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 @@
<item uniqueAttr="ONE">2</item>
<item uniqueAttr="TWO">2</item>
<itemRef>3</itemRef>
-</itemList>
\ No newline at end of file
+</itemList>
--- 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 @@
</xsd:simpleContent>
</xsd:complexType>
-</xsd:schema>
\ No newline at end of file
+</xsd:schema>
--- 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 @@
<?xml version="1.0"?>
-<S>-12345</S>
\ No newline at end of file
+<S>-12345</S>
--- 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 @@
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<B />
<C xsi:type="X" />
-</A>
\ No newline at end of file
+</A>
--- 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 @@
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<B xsi:type="X" />
<C />
-</A>
\ No newline at end of file
+</A>
--- 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 @@
<!NOTATION myNotation SYSTEM "somethingElse" >
-<!ENTITY myUnparsedEntity SYSTEM "something" NDATA myNotation >
\ No newline at end of file
+<!ENTITY myUnparsedEntity SYSTEM "something" NDATA myNotation >
--- 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 @@
<b>Is this EXSLT? No. no</b>
<c>Is this EXSLT? No. no</c>
</a>
-</html>
\ No newline at end of file
+</html>
--- 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}"
}
-
-
--- 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 @@
}
}
-
-
--- 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);
}
}
-
-
--- 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
+}
--- 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.
-
-
--- 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).
-
-
--- 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";
};
-
-
--- 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";
};
-
-
--- 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
--- 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
+}
--- 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 @@
}
}
}
-
-
--- 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
-
-
-
--- 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
+}
--- 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;
}
}
}
--- 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;
}
}
}
--- 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
-
-
--- 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
+}
--- 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<Boolean, String> runTest();
}
-
-
--- 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;
}
}
-
-
--- 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
+}
--- 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
-
-
--- 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
-
-
--- 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
-
-
--- /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);
+ }
+ }
+}
--- 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
--- 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<? extends Processor> processors;
- JavacTaskImpl(Context context) {
+ protected JavacTaskImpl(Context context) {
super(context, true);
args = Arguments.instance(context);
fileManager = context.get(JavaFileManager.class);
--- 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<MultiTaskListener> 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;
+ }
}
--- 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<ScopeListener> 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<WeakReference<ScopeListener>> 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<WeakReference<ScopeListener>> newListeners = new ListBuffer<>();
+ for (WeakReference<ScopeListener> 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<ScopeListener> 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<ScopeListener> 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() {
--- 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<Arguments> argsKey = new Context.Key<>();
+ public static final Context.Key<Arguments> argsKey = new Context.Key<>();
private String ownName;
private Set<String> classNames;
--- 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<JavaCompiler> compilerKey = new Context.Key<>();
+ public static final Context.Key<JavaCompiler> 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.
--- 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<String> buf = List.nil();
+ ListBuffer<JCExpression> opStack = new ListBuffer<>();
+ ListBuffer<JCLiteral> 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<JCExpression> 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<JCLiteral> litBuf,
+ ListBuffer<JCExpression> 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<JCLiteral> litBuf, ListBuffer<JCExpression> 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.
*/
--- 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<T> -> Factory<T> }
*/
- private final Map<Key<?>,Object> ht = new HashMap<>();
+ protected final Map<Key<?>,Object> ht = new HashMap<>();
/** Set the factory for the key in this context. */
public <T> void put(Key<T> key, Factory<T> fac) {
@@ -173,7 +173,7 @@
*/
private final Map<Class<?>, Key<?>> kt = new HashMap<>();
- private <T> Key<T> key(Class<T> clss) {
+ protected <T> Key<T> key(Class<T> clss) {
checkState(kt);
Key<T> k = uncheckedCast(kt.get(clss));
if (k == null) {
--- 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<Pair<JavaFileObject, Integer>> recorded = new HashSet<>();
+ protected Set<Pair<JavaFileObject, Integer>> recorded = new HashSet<>();
public boolean hasDiagnosticListener() {
return diagListener != null;
--- 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");
}
}
--- 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<T7093325> {
+
+ 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<T7093325>()
+ .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<Iterable<? extends JavaFileObject>> 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 {}";
}
--- 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<Void, Void> 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<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> 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();
- }
- }
-
-}
--- 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<IntersectionTypeCastTest> {
- 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<InterfaceKind> 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<IntersectionTypeCastTest>()
+ .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<CastInfo> allCastInfo() {
- ListBuffer<CastInfo> 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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- 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<InterfaceMethodHidingTest> {
- 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<InterfaceMethodHidingTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> 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());
}
}
}
--- 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<TestDefaultSuperCall> {
+
+ 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<ElementKind> enclosingElements;
List<String> enclosingNames;
List<String> 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<TestDefaultSuperCall>()
+ .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<String>(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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- 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<FileChecker> 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<File> roots) throws IOException {
+ long now = System.currentTimeMillis();
+ ArrayList<File> buf = new ArrayList<>();
+ for (File file : roots) {
+ Files.walkFileTree(file.toPath(), new SimpleFileVisitor<Path>() {
+ @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<FileChecker> {
+
+ 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<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
+ try {
+ Iterable<? extends JavaFileObject> files = fileManager().getJavaFileObjects(file);
+ final List<Element> analyzedElems = new ArrayList<>();
+ final List<CompilationUnitTree> trees = new ArrayList<>();
+ Iterable<? extends Element> 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<Pair<JCCompilationUnit, JCTree>> 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<Pair<JCCompilationUnit, JCTree>> trees) {
+ for (Pair<JCCompilationUnit, JCTree> 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<String> 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<Field> 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<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
- r.errors = 0;
- Iterable<? extends JavaFileObject> 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<Element> 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<? extends CompilationUnitTree> 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<? extends Element> elems = task.analyze();
- if (!elems.iterator().hasNext())
- throw new AttributionException("No results from analyze");
- List<Pair<JCCompilationUnit, JCTree>> 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<Pair<JCCompilationUnit, JCTree>> trees) {
- for (Pair<JCCompilationUnit, JCTree> 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<String> 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<Field> 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<JavaFileObject> {
- Reporter(PrintWriter out) {
- this.out = out;
- }
-
- public void report(Diagnostic<? extends JavaFileObject> 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
--- 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<DiamondAndInnerClassTest> {
+
+ enum TypeArgumentKind implements ComboParameter {
NONE(""),
STRING("<String>"),
INTEGER("<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<X> { A1(X x1) { } #B }"),
- TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #B } }"),
- THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { A3(X1 x1, X2 x2, X3 x3) { } #B } } }");
+ enum InnerClassDeclArity implements ComboParameter {
+ ONE(1, "class A1<X> { A1(X x1) { } #{BODY} }"),
+ TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #{BODY} } }"),
+ THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { 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<DiamondAndInnerClassTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- 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<GenericOverrideTest> {
enum SourceLevel {
SOURCE_7("-source", "7"),
@@ -58,24 +58,29 @@
}
}
- enum SignatureKind {
+ enum SignatureKind implements ComboParameter {
NON_GENERIC(""),
GENERIC("<X>");
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("<Number>"),
@@ -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<GenericOverrideTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- 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<FunctionalInterfaceConversionTest> {
+
+ 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 <X> #R m(#ARG s) throws #T;");
+ NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"),
+ GENERIC("public abstract <X> #{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<FunctionalInterfaceConversionTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound = false;
-
- @Override
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
}
--- 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<LambdaParserTest> {
- 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<LambdaParserTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- 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<MethodReferenceParserTest> {
-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("<X>"),
TWO("<X,Y>");
@@ -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<MethodReferenceParserTest>()
+ .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<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- /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<Void, Void> 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<JavaFileObject> {
+
+ boolean diagFound;
+ ArrayList<String> diags = new ArrayList<>();
+
+ public void report(Diagnostic<? extends JavaFileObject> 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();
+ }
+ }
+
+}
--- 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<TestInvokeDynamic> {
- 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<TestInvokeDynamic>()
+ .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<Iterable<? extends JavaFileObject>> 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<Void, Void> implements TaskListener {
MethodSymbol bsm;
@@ -475,26 +444,4 @@
return null;
}
}
-
- static class DiagChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> 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();
- }
- }
-
}
--- 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<TestLambdaToMethodStats> {
+
+ 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<TestLambdaToMethodStats>()
+ .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<Diagnostic<? extends JavaFileObject>> 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<JavaFileObject> {
-
- boolean altMetafactory;
- boolean bridge;
- boolean lambda;
-
- public void report(Diagnostic<? extends JavaFileObject> 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());
}
}
}
--- 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<TestLambdaBytecode> {
-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<TestLambdaBytecode>()
+ .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<Iterable<? extends JavaFileObject>> 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<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> 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();
- }
- }
-
}
--- 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<StructuralMostSpecificTest> {
- 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<StructuralMostSpecificTest>()
+ .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<Iterable<? extends Element>> 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<JavaFileObject> {
-
- boolean ambiguityFound;
- String mostSpecificSig;
+ boolean ambiguityFound(Result<Iterable<? extends Element>> result) {
+ return result.containsKey("compiler.err.ref.ambiguous");
+ }
- public void report(Diagnostic<? extends JavaFileObject> 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<Iterable<? extends Element>> result) {
+ List<Diagnostic<? extends JavaFileObject>> 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;
}
}
-
}
--- 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<TypeInferenceComboTest> {
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<JavaFileObject> {
-
- boolean errorFound = false;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
+ public static void main(String[] args) {
+ new ComboTestHelper<TypeInferenceComboTest>()
+ .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;
+ }
}
--- 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<StandardJavaFileManager> fm =
- new ThreadLocal<StandardJavaFileManager>() {
- @Override protected StandardJavaFileManager initialValue() {
- return comp.getStandardFileManager(null, null, null);
- }
- };
-
-}
--- /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<X extends ComboInstance<X>> {
+
+ /** The test instance result status. */
+ private ResultStatus resultStatus = ResultStatus.PASSED;
+
+ /** The test instance execution environment. */
+ private ComboTestHelper<X>.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<X>.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
--- /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:
+ * <p>
+ * #{MAJOR}
+ * #{MAJOR.}
+ * #{MAJOR.MINOR}
+ * <p>
+ * 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<D> 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();
+ }
+ }
+ }
+}
--- /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<JavaFileObject> sources = List.nil();
+
+ /** Options associated with this task. */
+ private List<String> options = List.nil();
+
+ /** Diagnostic collector. */
+ private DiagnosticCollector diagsCollector = new DiagnosticCollector();
+
+ /** Output writer. */
+ private Writer out;
+
+ /** Listeners associated with this task. */
+ private List<TaskListener> 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<? extends String> 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<Iterable<? extends CompilationUnitTree>> parse() throws IOException {
+ return new Result<>(getTask().parse());
+ }
+
+ /**
+ * Parse and analyzes the sources associated with this task.
+ */
+ public Result<Iterable<? extends Element>> analyze() throws IOException {
+ return new Result<>(getTask().analyze());
+ }
+
+ /**
+ * Parse, analyze and perform code generation for the sources associated with this task.
+ */
+ public Result<Iterable<? extends JavaFileObject>> 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<D> {
+
+ /** 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<Diagnostic<? extends JavaFileObject>> diagnosticsForKind(Diagnostic.Kind kind) {
+ List<Diagnostic<? extends JavaFileObject>> diags = diagsCollector.diagsByKind.get(kind);
+ return diags != null ? diags : List.nil();
+ }
+
+ /**
+ * Retrieve the list of diagnostics with given key.
+ */
+ public List<Diagnostic<? extends JavaFileObject>> diagnosticsForKey(String key) {
+ List<Diagnostic<? extends JavaFileObject>> 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<String, ComboParameter> 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<JavaFileObject> {
+
+ Map<Diagnostic.Kind, List<Diagnostic<? extends JavaFileObject>>> diagsByKind = new HashMap<>();
+ Map<String, List<Diagnostic<? extends JavaFileObject>>> diagsByKeys = new HashMap<>();
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ List<Diagnostic<? extends JavaFileObject>> 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));
+ }
+ }
+}
--- /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:
+ * <p>
+ * 'public' 'class'
+ * 'public' interface'
+ * 'package-private' 'class'
+ * 'package-private' 'interface'
+ * ...
+ * <p>
+ * 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?).
+ * <p>
+ * 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.
+ * <p>
+ * 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<X extends ComboInstance<X>> {
+
+ /** Failure mode. */
+ FailMode failMode = FailMode.FAIL_FAST;
+
+ /** Ignore mode. */
+ IgnoreMode ignoreMode = IgnoreMode.IGNORE_NONE;
+
+ /** Combo test instance filter. */
+ Optional<Predicate<X>> optFilter = Optional.empty();
+
+ /** Combo test dimensions. */
+ List<DimensionInfo<?>> 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<X> withFailMode(FailMode failMode) {
+ this.failMode = failMode;
+ return this;
+ }
+
+ /**
+ * Set ignore mode for this combo test.
+ */
+ public ComboTestHelper<X> withIgnoreMode(IgnoreMode ignoreMode) {
+ this.ignoreMode = ignoreMode;
+ return this;
+ }
+
+ /**
+ * Set a filter for combo test instances to be ignored.
+ */
+ public ComboTestHelper<X> withFilter(Predicate<X> 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 <D> ComboTestHelper<X> 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 <D> ComboTestHelper<X> withDimension(String name, DimensionSetter<X, D> 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 <D> ComboTestHelper<X> 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 <D> ComboTestHelper<X> withArrayDimension(String name, ArrayDimensionSetter<X, D> 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<X> 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<X> instanceBuilder, Consumer<X> 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<DimensionBinding<?>> bindings, Supplier<X> instanceBuilder, Optional<Consumer<X>> 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<X> instanceBuilder, Optional<Consumer<X>> initAction, List<DimensionBinding<?>> 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<X extends ComboInstance<X>, 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<X extends ComboInstance<X>, 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<D> {
+ String name;
+ D[] dims;
+ boolean isParameter;
+ Optional<DimensionSetter<X, D>> optSetter;
+
+ DimensionInfo(String name, D[] dims, DimensionSetter<X, D> 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<D> extends DimensionInfo<D> {
+ public ArrayDimensionInfo(String name, D[] dims, int index, ArrayDimensionSetter<X, D> 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 d;
+ DimensionInfo<D> info;
+
+ DimensionBinding(D d, DimensionInfo<D> 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<String> lastFailure = Optional.empty();
+ Optional<Throwable> 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<DimensionBinding<?>> bindings;
+ Map<String, ComboParameter> parametersCache = new HashMap<>();
+
+ @SuppressWarnings({"Unchecked", "rawtypes"})
+ Env(List<DimensionBinding<?>> 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;
+ }
+ }
+}
+
+
+
--- /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.
+ * <p>
+ * 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<CompilationUnitTree> 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<Void, Void>() {
+ @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
+ }
+
+ <T> void drop(Key<T> k) {
+ ht.remove(k);
+ }
+
+ <T> void drop(Class<T> 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<JavaCompiler> 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<Log> 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<JavaFileObject>() {
+ DiagnosticListener<JavaFileObject> cachedListener;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (cachedListener == null) {
+ cachedListener = context.get(DiagnosticListener.class);
+ }
+ cachedListener.report(diagnostic);
+ }
+ };
+ }
+ }
+}
--- 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<DisjunctiveTypeWellFormednessTest> {
+
+ 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<DisjunctiveTypeWellFormednessTest>()
+ .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<JavaFileObject> {
-
- int errorsFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
- diagnostic.getCode().startsWith("compiler.err.multicatch.types.must.be.disjoint")) {
- errorsFound++;
- }
- }
- }
-
}
--- /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;
+}
--- 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<JavaFileObject> dc = new DiagnosticCollector<>();
- List<JavaSource> 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<BitWiseOperators> {
+
+ 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<BitWiseOperators>()
+ .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());
+ }
+ }
}
--- 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();
+ }
+
}
--- 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<T7042566> {
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<JavaFileObject> {
+ public static void main(String[] args) {
+ new ComboTestHelper<T7042566>()
+ .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<String> 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<? extends JavaFileObject> 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<Iterable<? extends JavaFileObject>> 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<Iterable<? extends JavaFileObject>> 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);
+ }
+ }
}
--- 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<Warn4> {
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("<Z> void #name(List<Z>#arity arg) { #body }",
+ INVARIANT_TVAR("<Z> void #NAME(List<Z>#ARITY arg) { #BODY }",
new Warning[][] {both, both, error, both, error}),
- TVAR("<Z> void #name(Z#arity arg) { #body }",
+ TVAR("<Z> void #NAME(Z#ARITY arg) { #BODY }",
new Warning[][] {both, both, both, both, vararg}),
- INVARIANT("void #name(List<String>#arity arg) { #body }",
+ INVARIANT("void #NAME(List<String>#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<Warn4>()
+ .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<Warning> warnings = new HashSet<>();
+ for (Diagnostic<? extends JavaFileObject> 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<JavaFileObject> {
-
- Set<Warning> warnings = new HashSet<>();
-
- public void report(Diagnostic<? extends JavaFileObject> 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);
- }
- }
- }
- }
-
}
--- 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<Warn5> {
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 <X>#N(X... x)", false, true),
- VARARGS_STRING("#K #N(String... x)", true, true),
- ARRAY_X("#K <X>#N(X[] x)", false, false),
- ARRAY_STRING("#K #N(String[] x)", true, false);
+ enum SignatureKind implements ComboParameter {
+ VARARGS_X("<X>#{NAME}(X... x)", false, true),
+ VARARGS_STRING("#{NAME}(String... x)", true, true),
+ ARRAY_X("<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<Warn5>()
+ .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<WarningKind> foundWarnings = EnumSet.noneOf(WarningKind.class);
+ for (Diagnostic.Kind kind : new Kind[] { Kind.ERROR, Kind.MANDATORY_WARNING, Kind.WARNING}) {
+ for (Diagnostic<? extends JavaFileObject> 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<WarningKind> 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<JavaFileObject> {
-
- EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
-
- public void report(Diagnostic<? extends JavaFileObject> 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);
- }
- }
-
}
--- 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
--- 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
--- 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
--- 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)
--- 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
--- 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
--- 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
--- 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
--- 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<String> 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;
}
--- 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
--- 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();
}
/**
--- 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;
+ }
+ }
}
--- 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<IdentNode> params = functionNode.getParameters();
+ assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!";
final List<IdentNode> 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;
}
--- 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<Set<String>> thisProperties = new ArrayDeque<>();
private final Map<String, Symbol> 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<Expression> 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;
}
--- 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<LexicalContext>(new LexicalContext()) {
- @Override
- public Node leaveBlock(final Block block) {
- if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
- return block.setStatements(lc, Collections.<Statement>emptyList());
- }
- return super.leaveBlock(block);
- }
- });
- }
-}
--- /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<LexicalContext> {
+ private final Deque<RecompilableScriptFunctionData> 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.<Statement>emptyList()));
+ }
+ return functionNode;
+ }
+}
--- 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<LexicalContext>(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<LexicalContext>(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'";
}
},
--- 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<Integer, byte[]> serializedAsts = new HashMap<>();
-
/**
* Compilation phases that a compilation goes through
*/
public static class CompilationPhases implements Iterable<CompilationPhase> {
/**
- * 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<CompilationPhase> 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)) {
--- 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);
--- 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;
--- 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<Integer, Type[]> paramTypeMap = new HashMap<>();
- private final Map<Integer, Type> 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<empty>");
- return sb.toString();
- }
-
- for (final Map.Entry<Integer, Type[]> 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();
}
--- 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<Symbol, Symbol> replacements) {
+ if (symbols.isEmpty()) {
+ return this;
+ }
+ final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols);
+ for (final Map.Entry<String, Symbol> 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<Symbol> 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);
}
--- 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
--- 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<IdentNode> 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
--- 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<CaseNode> 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));
}
}
--- 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<Symbol> {
+public final class Symbol implements Comparable<Symbol>, 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;
+ }
}
--- 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<Block> 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<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) {
+ private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> 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<Block> 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
--- 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)
--- 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);
--- 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<IdentNode> 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<Expression> 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);
}
--- 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),
--- /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();
+ }
+}
--- 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")
--- 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<Integer, RecompilableScriptFunctionData> nestedFunctions,
final Map<String, Integer> externalScopeDepths,
- final Set<String> internalSymbols,
- final byte[] serializedAst) {
+ final Set<String> 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<FunctionNode> 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<FunctionNode> cachedAst;
+
+ SerializedAst(final FunctionNode fn, final Reference<FunctionNode> 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<Symbol, Symbol> 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<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<>()) : null;
+ FunctionNode newFn = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(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());
--- 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;
}
--- 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;
- }
-
-}
--- 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);
}
--- 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);
}
/**
--- 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<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
+ private static final ClassValue<String> FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue<String>() {
@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:<name>
+ 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() {
--- 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);
}
}
--- 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
--- 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
--- 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
--- /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); }
+
--- /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
--- /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);
--- 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.
--- /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);
--- /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;
+}
--- /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" +
+ "]");
--- /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);
+
--- /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();
--- /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
--- 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
--- /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);
+}
+