From 90060a97f984c56274199cd425a8a5e969cf9ee5 Mon Sep 17 00:00:00 2001 From: Dmitry Markov Date: Wed, 13 Dec 2017 14:41:27 +0000 Subject: [PATCH 01/25] 8154405: AccessControlException by URLPermission check Reviewed-by: serb, ssadetsky, mullan --- .../share/classes/java/awt/Toolkit.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index 489ee4ff695..7a4372ace66 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -673,11 +673,13 @@ public abstract class Toolkit { *

* This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * {@code checkPermission} method with the - * url.openConnection().getPermission() permission to ensure - * that the access to the image is allowed. For compatibility - * with pre-1.2 security managers, if the access is denied with - * {@code FilePermission} or {@code SocketPermission}, + * {@code checkPermission} method with the corresponding + * permission to ensure that the access to the image is allowed. + * If the connection to the specified URL requires + * either {@code URLPermission} or {@code SocketPermission}, + * then {@code URLPermission} is used for security checks. + * For compatibility with pre-1.2 security managers, if the access + * is denied with {@code FilePermission} or {@code SocketPermission}, * the method throws the {@code SecurityException} * if the corresponding 1.1-style SecurityManager.checkXXX method * also denies permission. @@ -717,11 +719,13 @@ public abstract class Toolkit { *

* This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * {@code checkPermission} method with the - * url.openConnection().getPermission() permission to ensure - * that the image creation is allowed. For compatibility - * with pre-1.2 security managers, if the access is denied with - * {@code FilePermission} or {@code SocketPermission}, + * {@code checkPermission} method with the corresponding + * permission to ensure that the image creation is allowed. + * If the connection to the specified URL requires + * either {@code URLPermission} or {@code SocketPermission}, + * then {@code URLPermission} is used for security checks. + * For compatibility with pre-1.2 security managers, if the access + * is denied with {@code FilePermission} or {@code SocketPermission}, * the method throws {@code SecurityException} * if the corresponding 1.1-style SecurityManager.checkXXX method * also denies permission. From 9ecafd93f5825e9c507d81e2cc15171db33d6b4c Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 13 Dec 2017 14:21:12 -0800 Subject: [PATCH 02/25] 8188894: jdk/jshell/ToolShiftTabTest.java failed with IllegalStateException Reviewed-by: jlahoda --- .../jdk/jshell/ToolShiftTabTest.java | 13 ++++++------ test/langtools/jdk/jshell/UITesting.java | 20 ++++++++++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/test/langtools/jdk/jshell/ToolShiftTabTest.java b/test/langtools/jdk/jshell/ToolShiftTabTest.java index 68aeccf6f02..8ed785537c0 100644 --- a/test/langtools/jdk/jshell/ToolShiftTabTest.java +++ b/test/langtools/jdk/jshell/ToolShiftTabTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8166334 + * @bug 8166334 8188894 * @summary test shift-tab shortcuts "fixes" * @modules * jdk.jshell/jdk.internal.jshell.tool.resources:open @@ -107,11 +107,12 @@ public class ToolShiftTabTest extends UITesting { public void testFixImport() throws Exception { doRunTest((inputSink, out) -> { - inputSink.write("Frame"); - inputSink.write(FIX + "i"); - inputSink.write("1"); - inputSink.write(".WIDTH\n"); - waitOutput(out, "==> 1"); + do { + inputSink.write("Frame"); + inputSink.write(FIX + "i"); + inputSink.write("1"); + inputSink.write(".WIDTH\n"); + } while (!waitOutput(out, "==> 1", "Results may be incomplete")); inputSink.write("/import\n"); waitOutput(out, "| import java.awt.Frame"); diff --git a/test/langtools/jdk/jshell/UITesting.java b/test/langtools/jdk/jshell/UITesting.java index 3253a41aec1..f2629835eec 100644 --- a/test/langtools/jdk/jshell/UITesting.java +++ b/test/langtools/jdk/jshell/UITesting.java @@ -135,8 +135,19 @@ public class UITesting { } protected void waitOutput(StringBuilder out, String expected) { + waitOutput(out, expected, null); + } + + // Return true if expected is found, false if secondary is found, + // otherwise, time out with an IllegalStateException + protected boolean waitOutput(StringBuilder out, String expected, String secondary) { expected = expected.replaceAll("\n", laxLineEndings ? "\r?\n" : System.getProperty("line.separator")); Pattern expectedPattern = Pattern.compile(expected, Pattern.DOTALL); + Pattern secondaryPattern = null; + if (secondary != null) { + secondary = secondary.replaceAll("\n", laxLineEndings ? "\r?\n" : System.getProperty("line.separator")); + secondaryPattern = Pattern.compile(secondary, Pattern.DOTALL); + } synchronized (out) { long s = System.currentTimeMillis(); @@ -144,7 +155,14 @@ public class UITesting { Matcher m = expectedPattern.matcher(out); if (m.find()) { out.delete(0, m.end()); - return ; + return true; + } + if (secondaryPattern != null) { + m = secondaryPattern.matcher(out); + if (m.find()) { + out.delete(0, m.end()); + return false; + } } long e = System.currentTimeMillis(); if ((e - s) > TIMEOUT) { From b9ff3a75b791e28dd8c03482d1d0d996cee1b7ea Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 14 Dec 2017 20:25:09 +0000 Subject: [PATCH 03/25] Added tag jdk-11+0 for changeset 0ee20aad71c4 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0a1b78991e9..9c363b2a5fd 100644 --- a/.hgtags +++ b/.hgtags @@ -460,3 +460,4 @@ a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32 bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33 89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34 d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35 +0ee20aad71c4f33c426372b4c8bcc1235ce2ec08 jdk-11+0 From 1a5f4b8fa27e2f9b0866409ae06b720871b736f9 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 14 Dec 2017 13:16:33 -0800 Subject: [PATCH 04/25] 8193525: Intermittent failures of TestModulePackages.java Reviewed-by: darcy --- .../jdk/javadoc/doclet/testModules/TestModulePackages.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java index 2d11284aba0..4ae83788053 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java @@ -26,7 +26,9 @@ * @bug 8178070 * @summary Test packages table in module summary pages * @library /tools/lib ../lib - * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ModuleBuilder toolbox.ToolBox JavadocTester * @run main TestModulePackages */ From bc5ee0f53cc7a2306c258ddbb96ac99fbe2fe635 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Fri, 15 Dec 2017 06:18:09 +0000 Subject: [PATCH 05/25] Added tag jdk-10+36 for changeset 959f2f7cbaa6 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 9c363b2a5fd..31cd1fd1b4e 100644 --- a/.hgtags +++ b/.hgtags @@ -461,3 +461,4 @@ bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33 89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34 d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35 0ee20aad71c4f33c426372b4c8bcc1235ce2ec08 jdk-11+0 +959f2f7cbaa6d2ee45d50029744efb219721576c jdk-10+36 From 6a80c5906f7d51d12126284641e752b3c8fea0e6 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Fri, 15 Dec 2017 23:43:35 -0500 Subject: [PATCH 06/25] 8193364: verify_special_jvm_flags should not cause an assertion failure when version is bumped Reviewed-by: dcubed, coleenp --- src/hotspot/share/runtime/arguments.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 2540390b5c9..c1427e3aa77 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -674,6 +674,14 @@ static bool lookup_special_flag(const char *flag_name, size_t skip_index) { return false; } +// Verifies the correctness of the entries in the special_jvm_flags table. +// If there is a semantic error (i.e. a bug in the table) such as the obsoletion +// version being earlier than the deprecation version, then a warning is issued +// and verification fails - by returning false. If it is detected that the table +// is out of date, with respect to the current version, then a warning is issued +// but verification does not fail. This allows the VM to operate when the version +// is first updated, without needing to update all the impacted flags at the +// same time. static bool verify_special_jvm_flags() { bool success = true; for (size_t i = 0; special_jvm_flags[i].name != NULL; i++) { @@ -710,7 +718,6 @@ static bool verify_special_jvm_flags() { if (!version_less_than(JDK_Version::current(), flag.obsolete_in)) { if (Flag::find_flag(flag.name) != NULL) { warning("Global variable for obsolete special flag entry \"%s\" should be removed", flag.name); - success = false; } } } @@ -720,7 +727,6 @@ static bool verify_special_jvm_flags() { if (!version_less_than(JDK_Version::current(), flag.expired_in)) { if (Flag::find_flag(flag.name) != NULL) { warning("Global variable for expired flag entry \"%s\" should be removed", flag.name); - success = false; } } } From 691eb787324a4f2bc3c96eea8b7ff5e9bff29556 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 18 Dec 2017 18:51:40 -0800 Subject: [PATCH 07/25] 8173382: Add -source 11 and -target 11 to javac 8193291: Add SourceVersion.RELEASE_11 Reviewed-by: jjg, erikj, psandoz --- make/common/SetupJavaCompilers.gmk | 4 +- .../javax/lang/model/SourceVersion.java | 15 +++- .../com/sun/tools/javac/code/Source.java | 11 ++- .../com/sun/tools/javac/jvm/Profile.java | 6 +- .../com/sun/tools/javac/jvm/Target.java | 6 +- .../javac/processing/PrintingProcessor.java | 2 +- .../com/sun/tools/jdeprscan/LoadProc.java | 4 +- .../classes/com/sun/tools/jdeprscan/Main.java | 9 +- test/langtools/ProblemList.txt | 3 + test/langtools/tools/javac/api/T6265137.java | 2 +- test/langtools/tools/javac/api/T6395981.java | 4 +- .../lib/JavacTestingAbstractProcessor.java | 18 ++-- .../processing/model/TestSourceVersion.java | 4 +- .../javac/profiles/ProfileOptionTest.java | 1 + .../tools/javac/versions/Versions.java | 85 +++++++++++++------ 15 files changed, 118 insertions(+), 56 deletions(-) diff --git a/make/common/SetupJavaCompilers.gmk b/make/common/SetupJavaCompilers.gmk index 72bc7e442b7..02b6e442f67 100644 --- a/make/common/SetupJavaCompilers.gmk +++ b/make/common/SetupJavaCompilers.gmk @@ -69,7 +69,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE, \ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE, \ JVM := $(JAVA_JAVAC), \ JAVAC := $(NEW_JAVAC), \ - FLAGS := -source 10 -target 10 --doclint-format html5 \ + FLAGS := -source 11 -target 11 --doclint-format html5 \ -encoding ascii -XDignore.symbol.file=true $(JAVAC_WARNINGS), \ SERVER_DIR := $(SJAVAC_SERVER_DIR), \ SERVER_JVM := $(SJAVAC_SERVER_JAVA))) @@ -79,7 +79,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE, \ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE_NOWARNINGS, \ JVM := $(JAVA_JAVAC), \ JAVAC := $(NEW_JAVAC), \ - FLAGS := -source 10 -target 10 \ + FLAGS := -source 11 -target 11 \ -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS), \ SERVER_DIR := $(SJAVAC_SERVER_DIR), \ SERVER_JVM := $(SJAVAC_SERVER_JAVA))) diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index 5d8124aeda6..6a0c8f55e6e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -57,6 +57,7 @@ public enum SourceVersion { * 1.8: lambda expressions and default methods * 9: modules, small cleanups to 1.7 and 1.8 changes * 10: local-variable type inference (var) + * 11: to be determined changes */ /** @@ -162,7 +163,15 @@ public enum SourceVersion { * * @since 10 */ - RELEASE_10; + RELEASE_10, + + /** + * The version recognized by the Java Platform, Standard Edition + * 11. + * + * @since 11 + */ + RELEASE_11; // Note that when adding constants for newer releases, the // behavior of latest() and latestSupported() must be updated too. @@ -173,7 +182,7 @@ public enum SourceVersion { * @return the latest source version that can be modeled */ public static SourceVersion latest() { - return RELEASE_10; + return RELEASE_11; } private static final SourceVersion latestSupported = getLatestSupported(); @@ -183,6 +192,8 @@ public enum SourceVersion { String specVersion = System.getProperty("java.specification.version"); switch (specVersion) { + case "11": + return RELEASE_11; case "10": return RELEASE_10; case "9": diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 23447f62aae..107b94598ca 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -78,8 +78,11 @@ public enum Source { /** 1.9 modularity. */ JDK9("9"), - /** 1.10 covers the to be determined language features that will be added in JDK 10. */ - JDK10("10"); + /** 1.10 local-variable type inference (var). */ + JDK10("10"), + + /** 1.11 covers the to be determined language features that will be added in JDK 11. */ + JDK11("11"); private static final Context.Key sourceKey = new Context.Key<>(); @@ -108,6 +111,7 @@ public enum Source { tab.put("1.8", JDK8); // Make 8 an alias for 1.8 tab.put("1.9", JDK9); // Make 9 an alias for 1.9 tab.put("1.10", JDK10); // Make 10 an alias for 1.10 + // Decline to make 1.11 an alias for 11. } private Source(String name) { @@ -125,6 +129,7 @@ public enum Source { } public Target requiredTarget() { + if (this.compareTo(JDK11) >= 0) return Target.JDK1_11; if (this.compareTo(JDK10) >= 0) return Target.JDK1_10; if (this.compareTo(JDK9) >= 0) return Target.JDK1_9; if (this.compareTo(JDK8) >= 0) return Target.JDK1_8; @@ -247,6 +252,8 @@ public enum Source { return RELEASE_9; case JDK10: return RELEASE_10; + case JDK11: + return RELEASE_11; default: return null; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java index 1dceec9f725..c05c2f6488f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java @@ -40,9 +40,9 @@ import static com.sun.tools.javac.main.Option.PROFILE; * deletion without notice. */ public enum Profile { - COMPACT1("compact1", 1, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10), - COMPACT2("compact2", 2, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10), - COMPACT3("compact3", 3, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10), + COMPACT1("compact1", 1, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10, Target.JDK1_11), + COMPACT2("compact2", 2, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10, Target.JDK1_11), + COMPACT3("compact3", 3, Target.JDK1_8, Target.JDK1_9, Target.JDK1_10, Target.JDK1_11), DEFAULT { @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index b0413afb743..418d0746088 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -64,7 +64,10 @@ public enum Target { JDK1_9("1.9", 53, 0), /** JDK 10. */ - JDK1_10("1.10", 54, 0); + JDK1_10("1.10", 54, 0), + + /** JDK 11. */ + JDK1_11("11", 54, 0); // Initially an alias for JDK_10 private static final Context.Key targetKey = new Context.Key<>(); @@ -95,6 +98,7 @@ public enum Target { tab.put("8", JDK1_8); tab.put("9", JDK1_9); tab.put("10", JDK1_10); + tab.put("11", JDK1_11); } public final String name; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java index ecfc372fa6b..df339a0b150 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java @@ -55,7 +55,7 @@ import com.sun.tools.javac.util.StringUtils; * deletion without notice. */ @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_10) +@SupportedSourceVersion(SourceVersion.RELEASE_11) public class PrintingProcessor extends AbstractProcessor { PrintWriter writer; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/LoadProc.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/LoadProc.java index 8f0c761d6cf..9cac709031f 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/LoadProc.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/LoadProc.java @@ -50,7 +50,7 @@ import javax.lang.model.util.Elements; import javax.tools.Diagnostic; -import static javax.lang.model.SourceVersion.RELEASE_10; +import static javax.lang.model.SourceVersion.RELEASE_11; /** * Annotation processor for the Deprecation Scanner tool. @@ -58,7 +58,7 @@ import static javax.lang.model.SourceVersion.RELEASE_10; * */ @SupportedAnnotationTypes("java.lang.Deprecated") -@SupportedSourceVersion(RELEASE_10) +@SupportedSourceVersion(RELEASE_11) public class LoadProc extends AbstractProcessor { Elements elements; Messager messager; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java index 7dfbb31499a..115075264fd 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java @@ -106,7 +106,7 @@ public class Main implements DiagnosticListener { // Keep these updated manually until there's a compiler API // that allows querying of supported releases. final Set releasesWithoutForRemoval = Set.of("6", "7", "8"); - final Set releasesWithForRemoval = Set.of("9", "10"); + final Set releasesWithForRemoval = Set.of("9", "10", "11"); final Set validReleases; { @@ -358,14 +358,15 @@ public class Main implements DiagnosticListener { * Process classes from a particular JDK release, using only information * in this JDK. * - * @param release "6", "7", "8", "9", or "10" + * @param release "6", "7", "8", "9", "10", or "11" * @param classes collection of classes to process, may be empty * @return success value */ boolean processRelease(String release, Collection classes) throws IOException { options.addAll(List.of("--release", release)); - if (release.equals("9") || release.equals("10")) { + if (release.equals("9") || release.equals("10") || + release.equals("11")) { List rootMods = List.of("java.se", "java.se.ee"); TraverseProc proc = new TraverseProc(rootMods); JavaCompiler.CompilationTask task = @@ -481,7 +482,7 @@ public class Main implements DiagnosticListener { String dir = null; String jar = null; String jdkHome = null; - String release = "10"; + String release = "11"; List loadClasses = new ArrayList<>(); String csvFile = null; diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index 4cf72be2bc4..82c342f3346 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -54,6 +54,7 @@ tools/javac/annotations/typeAnnotations/referenceinfos/Lambda.java tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java 8057687 generic-all emit correct byte code an attributes for type annotations tools/javac/warnings/suppress/TypeAnnotations.java 8057683 generic-all improve ordering of errors with type annotations tools/javac/modules/SourceInSymlinkTest.java 8180263 windows-all fails when run on a subst drive +tools/javac/options/release/ReleaseOptionUnsupported.java 8193784 generic-all temporary until support for --release 11 is worked out ########################################################################### # @@ -76,3 +77,5 @@ tools/sjavac/ClasspathDependencies.java 8158002 generic-all Requires i ########################################################################### # # jdeps + +tools/jdeprscan/tests/jdk/jdeprscan/TestNotFound.java 8193784 generic-all temporary until support for --release 11 is worked out diff --git a/test/langtools/tools/javac/api/T6265137.java b/test/langtools/tools/javac/api/T6265137.java index fd7f02d3ed3..c319aa8d6db 100644 --- a/test/langtools/tools/javac/api/T6265137.java +++ b/test/langtools/tools/javac/api/T6265137.java @@ -52,7 +52,7 @@ public class T6265137 { String srcdir = System.getProperty("test.src"); Iterable files = fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(srcdir, "T6265137a.java"))); - javac.getTask(null, fm, dl, Arrays.asList("-target","10"), null, files).call(); + javac.getTask(null, fm, dl, Arrays.asList("-target","11"), null, files).call(); } } } diff --git a/test/langtools/tools/javac/api/T6395981.java b/test/langtools/tools/javac/api/T6395981.java index 7ac2a2ce11d..0ab7762ff72 100644 --- a/test/langtools/tools/javac/api/T6395981.java +++ b/test/langtools/tools/javac/api/T6395981.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6395981 6458819 7025784 8028543 8028544 + * @bug 6395981 6458819 7025784 8028543 8028544 8193291 * @summary JavaCompilerTool and Tool must specify version of JLS and JVMS * @author Peter von der Ah\u00e9 * @modules java.compiler @@ -31,7 +31,7 @@ * @run main/fail T6395981 * @run main/fail T6395981 RELEASE_3 RELEASE_5 RELEASE_6 * @run main/fail T6395981 RELEASE_0 RELEASE_1 RELEASE_2 RELEASE_3 RELEASE_4 RELEASE_5 RELEASE_6 - * @run main T6395981 RELEASE_3 RELEASE_4 RELEASE_5 RELEASE_6 RELEASE_7 RELEASE_8 RELEASE_9 RELEASE_10 + * @run main T6395981 RELEASE_3 RELEASE_4 RELEASE_5 RELEASE_6 RELEASE_7 RELEASE_8 RELEASE_9 RELEASE_10 RELEASE_11 */ import java.util.EnumSet; diff --git a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java index 72c758d20d6..818ccb288b1 100644 --- a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java +++ b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java @@ -110,7 +110,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { * corresponding platform visitor type. */ - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static abstract class AbstractAnnotationValueVisitor extends AbstractAnnotationValueVisitor9 { /** @@ -121,7 +121,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static abstract class AbstractElementVisitor extends AbstractElementVisitor9 { /** * Constructor for concrete subclasses to call. @@ -131,7 +131,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static abstract class AbstractTypeVisitor extends AbstractTypeVisitor9 { /** * Constructor for concrete subclasses to call. @@ -141,7 +141,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class ElementKindVisitor extends ElementKindVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -162,7 +162,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class ElementScanner extends ElementScanner9 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -181,7 +181,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class SimpleAnnotationValueVisitor extends SimpleAnnotationValueVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -202,7 +202,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class SimpleElementVisitor extends SimpleElementVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -223,7 +223,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class SimpleTypeVisitor extends SimpleTypeVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -244,7 +244,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_10) + @SupportedSourceVersion(RELEASE_11) public static class TypeKindVisitor extends TypeKindVisitor9 { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/test/langtools/tools/javac/processing/model/TestSourceVersion.java b/test/langtools/tools/javac/processing/model/TestSourceVersion.java index 3ce894e8b25..2145660920c 100644 --- a/test/langtools/tools/javac/processing/model/TestSourceVersion.java +++ b/test/langtools/tools/javac/processing/model/TestSourceVersion.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7025809 8028543 6415644 8028544 8029942 + * @bug 7025809 8028543 6415644 8028544 8029942 8193291 * @summary Test latest, latestSupported, underscore as keyword, etc. * @author Joseph D. Darcy * @modules java.compiler @@ -45,7 +45,7 @@ public class TestSourceVersion { } private static void testLatestSupported() { - if (SourceVersion.latest() != RELEASE_10 || + if (SourceVersion.latest() != RELEASE_11 || SourceVersion.latestSupported() != RELEASE_10) throw new RuntimeException("Unexpected release value(s) found:\n" + "latest:\t" + SourceVersion.latest() + "\n" + diff --git a/test/langtools/tools/javac/profiles/ProfileOptionTest.java b/test/langtools/tools/javac/profiles/ProfileOptionTest.java index 37c98fd715e..45d3b599f03 100644 --- a/test/langtools/tools/javac/profiles/ProfileOptionTest.java +++ b/test/langtools/tools/javac/profiles/ProfileOptionTest.java @@ -149,6 +149,7 @@ public class ProfileOptionTest { break; case JDK1_9: case JDK1_10: + case JDK1_11: if (p == Profile.DEFAULT) break; if (ise == null) diff --git a/test/langtools/tools/javac/versions/Versions.java b/test/langtools/tools/javac/versions/Versions.java index 52dfb9c5bc2..8e3fc8b026b 100644 --- a/test/langtools/tools/javac/versions/Versions.java +++ b/test/langtools/tools/javac/versions/Versions.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112 8028545 8000961 8030610 8028546 8188870 + * @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112 8028545 8000961 8030610 8028546 8188870 8173382 * @summary Check interpretation of -target and -source options * @modules java.compiler * jdk.compiler @@ -70,22 +70,24 @@ public class Versions { check("54.0", "-source 1.8"); check("54.0", "-source 1.9"); check("54.0", "-source 1.10"); + check("54.0", "-source 11"); - check_source_target("50.0", "6", "6"); - check_source_target("51.0", "6", "7"); - check_source_target("51.0", "7", "7"); - check_source_target("52.0", "6", "8"); - check_source_target("52.0", "7", "8"); - check_source_target("52.0", "8", "8"); - check_source_target("53.0", "6", "9"); - check_source_target("53.0", "7", "9"); - check_source_target("53.0", "8", "9"); - check_source_target("53.0", "9", "9"); - check_source_target("54.0", "6", "10"); - check_source_target("54.0", "7", "10"); - check_source_target("54.0", "8", "10"); - check_source_target("54.0", "9", "10"); - check_source_target("54.0", "10", "10"); + check_source_target(true, "50.0", "6", "6"); + check_source_target(true, "51.0", "6", "7"); + check_source_target(true, "51.0", "7", "7"); + check_source_target(true, "52.0", "6", "8"); + check_source_target(true, "52.0", "7", "8"); + check_source_target(true, "52.0", "8", "8"); + check_source_target(true, "53.0", "6", "9"); + check_source_target(true, "53.0", "7", "9"); + check_source_target(true, "53.0", "8", "9"); + check_source_target(true, "53.0", "9", "9"); + check_source_target(true, "54.0", "6", "10"); + check_source_target(true, "54.0", "7", "10"); + check_source_target(true, "54.0", "8", "10"); + check_source_target(true, "54.0", "9", "10"); + check_source_target(true, "54.0", "10", "10"); + check_source_target(false, "54.0", "11", "11"); checksrc16("-source 1.6"); checksrc16("-source 6"); @@ -108,8 +110,9 @@ public class Versions { checksrc110("-source 10"); checksrc110("-source 1.10", "-target 1.10"); checksrc110("-source 10", "-target 10"); - checksrc110("-target 1.10"); - checksrc110("-target 10"); + checksrc111("-source 11"); + checksrc111("-source 11", "-target 11"); + checksrc111("-target 11"); fail("-source 7", "-target 1.6", "Base.java"); fail("-source 8", "-target 1.6", "Base.java"); @@ -118,6 +121,8 @@ public class Versions { fail("-source 9", "-target 1.8", "Base.java"); fail("-source 10", "-target 1.7", "Base.java"); fail("-source 10", "-target 1.8", "Base.java"); + fail("-source 11", "-target 1.9", "Base.java"); + fail("-source 11", "-target 1.10", "Base.java"); fail("-source 1.5", "-target 1.5", "Base.java"); fail("-source 1.4", "-target 1.4", "Base.java"); @@ -139,20 +144,24 @@ public class Versions { System.out.printf("\n", fname); } - protected void check_source_target(String... args) { + protected void check_source_target(boolean dotOne, String... args) { printargs("check_source_target", args); - check_target(args[0], args[1], args[2]); - check_target(args[0], "1." + args[1], args[2]); + check_target(dotOne, args[0], args[1], args[2]); + if (dotOne) { + check_target(dotOne, args[0], "1." + args[1], args[2]); + } } - protected void check_target(String... args) { + protected void check_target(boolean dotOne, String... args) { check(args[0], "-source " + args[1], "-target " + args[2]); - check(args[0], "-source " + args[1], "-target 1." + args[2]); + if (dotOne) { + check(args[0], "-source " + args[1], "-target 1." + args[2]); + } } protected void check(String major, String... args) { printargs("check", args); - List jcargs = new ArrayList(); + List jcargs = new ArrayList<>(); jcargs.add("-Xlint:-options"); // add in args conforming to List requrements of JavaCompiler @@ -207,6 +216,8 @@ public class Versions { pass(newargs); newargs[asize] = "New18.java"; pass(newargs); + newargs[asize] = "New110.java"; + fail(newargs); } protected void checksrc19(String... args) { @@ -216,7 +227,20 @@ public class Versions { protected void checksrc110(String... args) { printargs("checksrc110", args); - checksrc19(args); + int asize = args.length; + String[] newargs = new String[asize+1]; + System.arraycopy(args, 0, newargs,0 , asize); + newargs[asize] = "New17.java"; + pass(newargs); + newargs[asize] = "New18.java"; + pass(newargs); + newargs[asize] = "New110.java"; + pass(newargs); + } + + protected void checksrc111(String... args) { + printargs("checksrc111", args); + checksrc110(args); } protected void pass(String... args) { @@ -347,6 +371,17 @@ public class Versions { "} \n" ); + /* + * Create a file with a new feature in 1.10, not in 1.9 : var + */ + writeSourceFile("New110.java", + "public class New110 { \n" + + " void m() { \n" + + " var tmp = new Thread(() -> { }); \n" + + " } \n" + + "} \n" + ); + } protected boolean checkClassFileVersion From e1069d367d116198cb2dfefc7c4de2e78ced181e Mon Sep 17 00:00:00 2001 From: Robert Field Date: Tue, 19 Dec 2017 11:37:00 -0800 Subject: [PATCH 08/25] 8179858: jshell tool: sync nomenclature from reference to online /help Reviewed-by: dlsmith, jjg --- .../jdk/internal/jshell/tool/JShellTool.java | 5 +- .../jshell/tool/resources/l10n.properties | 365 ++++++++++-------- .../jdk/jshell/CommandCompletionTest.java | 4 +- test/langtools/jdk/jshell/EditorTestBase.java | 2 +- test/langtools/jdk/jshell/ToolBasicTest.java | 10 +- test/langtools/jdk/jshell/ToolSimpleTest.java | 2 +- 6 files changed, 214 insertions(+), 174 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 79a0a1f71f8..8fc94b1b47b 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -1817,7 +1817,7 @@ public class JShellTool implements MessageHandler { // Documentation pseudo-commands registerCommand(new Command("/", - "help.id", + "help.slashID", arg -> cmdHelp("rerun"), EMPTY_COMPLETION_PROVIDER, CommandKind.HELP_ONLY)); @@ -1829,6 +1829,9 @@ public class JShellTool implements MessageHandler { registerCommand(new Command("intro", "help.intro", CommandKind.HELP_SUBJECT)); + registerCommand(new Command("id", + "help.id", + CommandKind.HELP_SUBJECT)); registerCommand(new Command("shortcuts", "help.shortcuts", CommandKind.HELP_SUBJECT)); diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 0d7e517f185..5c405b6e821 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -46,7 +46,7 @@ jshell.err.file.not.found = File ''{1}'' for ''{0}'' is not found. jshell.err.file.exception = File ''{1}'' for ''{0}'' threw exception: {2} jshell.err.file.filename = ''{0}'' requires a filename argument. -jshell.err.startup.unexpected.exception = Unexpected exception reading start-up: {0} +jshell.err.startup.unexpected.exception = Unexpected exception reading startup: {0} jshell.err.unexpected.exception = Unexpected exception: {0} jshell.err.invalid.command = Invalid command: {0} @@ -104,9 +104,9 @@ For example ''/help /list'' or ''/help intro''.\n\ Subjects:\n\ \n -jshell.err.no.snippet.with.id = No snippet with id: {0} +jshell.err.no.snippet.with.id = No snippet with ID: {0} jshell.err.end.snippet.range.less.than.start = End of snippet range less than start: {0} - {1} -jshell.err.range.requires.id = Snippet ranges require snippet ids: {0} +jshell.err.range.requires.id = Snippet ranges require snippet IDs: {0} jshell.err.exit.not.expression = The argument to /exit must be a valid integer expression, it is not an expression: {0} jshell.err.exit.bad.type = The argument to /exit must be a valid integer expression. The type is {1} : {0} @@ -114,7 +114,7 @@ jshell.err.exit.bad.value = The argument to /exit has bad value is {1} : {0} jshell.err.drop.arg =\ In the /drop argument, please specify an import, variable, method, or class to drop.\n\ -Specify by id or name. Use /list to see ids. Use /reset to reset all state. +Specify by ID or name. Use /list to see IDs. Use /reset to reset all state. jshell.err.failed = Failed. jshell.msg.native.method = Native Method jshell.msg.unknown.source = Unknown Source @@ -193,15 +193,15 @@ For more information see:\n\ /help shortcuts help.usage = \ -Usage: jshell

The type of the symbol may have changed while reading the + * method attributes (see the Signature attribute). This may be + * because of generic information or because anonymous synthetic + * parameters were added. The original type (as read from the + * method descriptor) is used to help guess the existence of * anonymous synthetic parameters. - * On completion, sym.savedParameter names will either be null (if - * no parameter names were found in the class file) or will be set to a - * list of names, one per entry in sym.type.getParameterTypes, with - * any missing names represented by the empty name. */ - void setParameterNames(MethodSymbol sym, Type jvmType) { - // if no names were found in the class file, there's nothing more to do - if (!haveParameterNameIndices) - return; + void setParameters(MethodSymbol sym, Type jvmType) { // If we get parameter names from MethodParameters, then we // don't need to skip. int firstParam = 0; @@ -2474,16 +2509,16 @@ public class ClassReader { // make a corresponding allowance here for the position of // the first parameter. Note that this assumes the // skipped parameter has a width of 1 -- i.e. it is not - // a double width type (long or double.) - if (sym.name == names.init && currentOwner.hasOuterInstance()) { - // Sometimes anonymous classes don't have an outer - // instance, however, there is no reliable way to tell so - // we never strip this$n - if (!currentOwner.name.isEmpty()) - firstParam += 1; - } + // a double width type (long or double.) + if (sym.name == names.init && currentOwner.hasOuterInstance()) { + // Sometimes anonymous classes don't have an outer + // instance, however, there is no reliable way to tell so + // we never strip this$n + if (!currentOwner.name.isEmpty()) + firstParam += 1; + } - if (sym.type != jvmType) { + if (sym.type != jvmType) { // reading the method attributes has caused the // symbol's type to be changed. (i.e. the Signature // attribute.) This may happen if there are hidden @@ -2493,21 +2528,55 @@ public class ClassReader { // at the beginning, and so skip over them. The // primary case for this is two hidden parameters // passed into Enum constructors. - int skip = Code.width(jvmType.getParameterTypes()) - - Code.width(sym.type.getParameterTypes()); - firstParam += skip; - } + int skip = Code.width(jvmType.getParameterTypes()) + - Code.width(sym.type.getParameterTypes()); + firstParam += skip; + } } List paramNames = List.nil(); - int index = firstParam; + ListBuffer params = new ListBuffer<>(); + int nameIndex = firstParam; + int annotationIndex = 0; for (Type t: sym.type.getParameterTypes()) { - int nameIdx = (index < parameterNameIndices.length - ? parameterNameIndices[index] : 0); - Name name = nameIdx == 0 ? names.empty : readName(nameIdx); + Name name = parameterName(nameIndex, paramNames); paramNames = paramNames.prepend(name); - index += sawMethodParameters ? 1 : Code.width(t); + VarSymbol param = new VarSymbol(PARAMETER, name, t, sym); + params.append(param); + if (parameterAnnotations != null) { + ParameterAnnotations annotations = parameterAnnotations[annotationIndex]; + if (annotations != null && annotations.proxies != null + && !annotations.proxies.isEmpty()) { + annotate.normal(new AnnotationCompleter(param, annotations.proxies)); + } + } + nameIndex += sawMethodParameters ? 1 : Code.width(t); + annotationIndex++; + } + if (parameterAnnotations != null && parameterAnnotations.length != annotationIndex) { + throw badClassFile("bad.runtime.invisible.param.annotations", sym); + } + Assert.checkNull(sym.params); + sym.params = params.toList(); + parameterAnnotations = null; + parameterNameIndices = null; + } + + + // Returns the name for the parameter at position 'index', either using + // names read from the MethodParameters, or by synthesizing a name that + // is not on the 'exclude' list. + private Name parameterName(int index, List exclude) { + if (parameterNameIndices != null && index < parameterNameIndices.length + && parameterNameIndices[index] != 0) { + return readName(parameterNameIndices[index]); + } + String prefix = "arg"; + while (true) { + Name argName = names.fromString(prefix + exclude.size()); + if (!exclude.contains(argName)) + return argName; + prefix += "$"; } - sym.savedParameterNames = paramNames.reverse(); } /** diff --git a/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.java b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.java new file mode 100644 index 00000000000..c2d153d09f3 --- /dev/null +++ b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Google Inc. 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 8007720 8177486 + * @summary class reading of named parameters + * @library /tools/javac/lib + * @modules java.compiler + * jdk.compiler + * @compile -parameters ClassReaderTest.java MethodParameterProcessor.java + * @compile/process/ref=ClassReaderTest.out -proc:only -processor MethodParameterProcessor ClassReaderTest ClassReaderTest$I ClassReaderTest$E + */ + +import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; + +public class ClassReaderTest { + + @Retention(RUNTIME) + @interface RuntimeAnnoOne { + int value() default 0; + } + + @Retention(RUNTIME) + @interface RuntimeAnnoTwo { + int value() default 0; + } + + @Retention(CLASS) + @interface ClassAnno { + int value() default 0; + } + + @MethodParameterProcessor.ParameterNames + void f( + @RuntimeAnnoOne(1) @RuntimeAnnoTwo(2) @ClassAnno(3) int a, + @RuntimeAnnoOne(4) @RuntimeAnnoTwo(5) @ClassAnno(6) String b) {} + + class I { + @MethodParameterProcessor.ParameterNames + I(@ClassAnno(7) int d, @RuntimeAnnoOne(8) String e, Object o) {} + } + + enum E { + ONE(42, ""); + + @MethodParameterProcessor.ParameterNames + E(int x, @RuntimeAnnoOne(9) String s) {} + } +} diff --git a/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.out b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.out new file mode 100644 index 00000000000..eaf12e3d9c7 --- /dev/null +++ b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/ClassReaderTest.out @@ -0,0 +1,3 @@ +Note: ClassReaderTest.E.(x, @ClassReaderTest.RuntimeAnnoOne(9) s) +Note: ClassReaderTest.I.(@ClassReaderTest.ClassAnno(7) d, @ClassReaderTest.RuntimeAnnoOne(8) e, o) +Note: ClassReaderTest.f(@ClassReaderTest.ClassAnno(3) @ClassReaderTest.RuntimeAnnoOne(1) @ClassReaderTest.RuntimeAnnoTwo(2) a, @ClassReaderTest.ClassAnno(6) @ClassReaderTest.RuntimeAnnoOne(4) @ClassReaderTest.RuntimeAnnoTwo(5) b) diff --git a/test/langtools/tools/javac/MethodParameters/ClassReaderTest/MethodParameterProcessor.java b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/MethodParameterProcessor.java new file mode 100644 index 00000000000..faa087cadaf --- /dev/null +++ b/test/langtools/tools/javac/MethodParameters/ClassReaderTest/MethodParameterProcessor.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google Inc. 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.util.stream.Collectors.joining; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; + +@SupportedAnnotationTypes("MethodParameterProcessor.ParameterNames") +public class MethodParameterProcessor extends JavacTestingAbstractProcessor { + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) + @interface ParameterNames { + String[] value() default {}; + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element element : roundEnv.getElementsAnnotatedWith(ParameterNames.class)) { + ExecutableElement exec = (ExecutableElement)element; + String message = printNamesAndAnnotations(exec); + messager.printMessage(Kind.NOTE, message); + } + return false; + } + + private String printNamesAndAnnotations(ExecutableElement exec) { + return String.format("%s.%s(%s)", + exec.getEnclosingElement(), + exec.getSimpleName(), + exec.getParameters().stream().map(this::printParameter).collect(joining(", "))); + } + + private String printParameter(VariableElement param) { + return param.getAnnotationMirrors().stream().map(String::valueOf).collect(joining(" ")) + + (param.getAnnotationMirrors().isEmpty() ? "" : " ") + + param.getSimpleName(); + } +} diff --git a/test/langtools/tools/javac/lib/DPrinter.java b/test/langtools/tools/javac/lib/DPrinter.java index d681d642f76..fbf69640291 100644 --- a/test/langtools/tools/javac/lib/DPrinter.java +++ b/test/langtools/tools/javac/lib/DPrinter.java @@ -1233,7 +1233,6 @@ public class DPrinter { public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { // code printList("params", sym.params); - printList("savedParameterNames", sym.savedParameterNames); return visitSymbol(sym, null); } From ede41aa311e41a66eb15cd833d2ba4c0cdac4232 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 20 Dec 2017 15:33:31 +0000 Subject: [PATCH 10/25] 8057650: uniform error diagnostics for inconsistent inherited method signatures Consolidate diagnostics for bad overrides Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Check.java | 20 ++++++++++--------- .../tools/javac/resources/compiler.properties | 15 +++++++++----- test/langtools/tools/javac/BadCovar.out | 2 +- .../javac/InconsistentInheritedSignature.out | 2 +- .../OverrideChecks/InconsistentReturn.out | 2 +- .../tools/javac/defaultMethods/Neg01.out | 2 +- .../tools/javac/defaultMethods/Neg02.out | 2 +- .../tools/javac/defaultMethods/Neg14.out | 2 +- .../IncompatibleDescsInFunctionalIntf.java | 3 ++- .../diags/examples/TypesIncompatible.java | 3 ++- .../TypesIncompatibleAbstractDefault.java | 3 ++- .../TypesIncompatibleUnrelatedDefaults.java | 3 ++- .../javac/generics/6294779/T6294779c.out | 2 +- .../javac/generics/abstract/T4717181c.out | 2 +- .../generics/rawOverride/7157798/Test3.out | 10 +++++----- .../generics/typevars/4856983/T4856983a.out | 2 +- .../generics/typevars/4856983/T4856983b.out | 2 +- .../generics/typevars/6199146/T6199146.out | 2 +- .../generics/wildcards/7034495/T7034495.out | 2 +- .../tools/javac/lambda/BadConv04.out | 2 +- .../BridgeMethodsTemplateTest.java | 6 +++--- .../javac/lambda/funcInterfaces/NonSAM2.out | 2 +- .../tools/javac/miranda/4711056/T1.out | 2 +- 23 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 4f1d7142bbb..b3999f56571 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -1976,8 +1976,8 @@ public class Check { types.covariantReturnType(rt2, rt1, types.noWarnings)) || checkCommonOverriderIn(s1,s2,site); if (!compat) { - log.error(pos, Errors.TypesIncompatibleDiffRet(t1, t2, s2.name + - "(" + types.memberType(t2, s2).getParameterTypes() + ")")); + log.error(pos, Errors.TypesIncompatible(t1, t2, + Fragments.IncompatibleDiffRet(s2.name, types.memberType(t2, s2).getParameterTypes()))); return s2; } } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && @@ -2563,20 +2563,22 @@ public class Check { //strong semantics - issue an error if two sibling interfaces //have two override-equivalent defaults - or if one is abstract //and the other is default - String errKey; + Fragment diagKey; Symbol s1 = defaults.first(); Symbol s2; if (defaults.size() > 1) { - errKey = "types.incompatible.unrelated.defaults"; s2 = defaults.toList().tail.head; + diagKey = Fragments.IncompatibleUnrelatedDefaults(Kinds.kindName(site.tsym), site, + m.name, types.memberType(site, m).getParameterTypes(), + s1.location(), s2.location()); + } else { - errKey = "types.incompatible.abstract.default"; s2 = abstracts.first(); + diagKey = Fragments.IncompatibleAbstractDefault(Kinds.kindName(site.tsym), site, + m.name, types.memberType(site, m).getParameterTypes(), + s1.location(), s2.location()); } - log.error(pos, errKey, - Kinds.kindName(site.tsym), site, - m.name, types.memberType(site, m).getParameterTypes(), - s1.location(), s2.location()); + log.error(pos, Errors.TypesIncompatible(s1.location().type, s2.location().type, diagKey)); break; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index de2600eaa3f..3ca606e2581 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1136,16 +1136,21 @@ compiler.err.type.var.more.than.once=\ compiler.err.type.var.more.than.once.in.result=\ type variable {0} occurs more than once in type of {1}; cannot be left uninstantiated -# 0: type, 1: type, 2: string -compiler.err.types.incompatible.diff.ret=\ - types {0} and {1} are incompatible; both define {2}, but with unrelated return types +# 0: type, 1: type, 2: fragment +compiler.err.types.incompatible=\ + types {0} and {1} are incompatible;\n\ + {2} + +# 0: name, 1: list of type +compiler.misc.incompatible.diff.ret=\ + both define {0}({1}), but with unrelated return types # 0: kind name, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol -compiler.err.types.incompatible.unrelated.defaults=\ +compiler.misc.incompatible.unrelated.defaults=\ {0} {1} inherits unrelated defaults for {2}({3}) from types {4} and {5} # 0: kind name, 1: type, 2: name, 3: list of type, 4: symbol, 5: symbol -compiler.err.types.incompatible.abstract.default=\ +compiler.misc.incompatible.abstract.default=\ {0} {1} inherits abstract and default for {2}({3}) from types {4} and {5} # 0: name, 1: kind name, 2: symbol diff --git a/test/langtools/tools/javac/BadCovar.out b/test/langtools/tools/javac/BadCovar.out index 29bdbcc3d94..59fd5fa10d6 100644 --- a/test/langtools/tools/javac/BadCovar.out +++ b/test/langtools/tools/javac/BadCovar.out @@ -1,2 +1,2 @@ -BadCovar.java:22:10: compiler.err.types.incompatible.diff.ret: bad.covar.B, bad.covar.A, f() +BadCovar.java:22:10: compiler.err.types.incompatible: bad.covar.B, bad.covar.A, (compiler.misc.incompatible.diff.ret: f, ) 1 error diff --git a/test/langtools/tools/javac/InconsistentInheritedSignature.out b/test/langtools/tools/javac/InconsistentInheritedSignature.out index b4fd9a96d08..fe908134e1f 100644 --- a/test/langtools/tools/javac/InconsistentInheritedSignature.out +++ b/test/langtools/tools/javac/InconsistentInheritedSignature.out @@ -1,2 +1,2 @@ -InconsistentInheritedSignature.java:17:1: compiler.err.types.incompatible.diff.ret: I2, I1, f() +InconsistentInheritedSignature.java:17:1: compiler.err.types.incompatible: I2, I1, (compiler.misc.incompatible.diff.ret: f, ) 1 error diff --git a/test/langtools/tools/javac/OverrideChecks/InconsistentReturn.out b/test/langtools/tools/javac/OverrideChecks/InconsistentReturn.out index 6adccb4a11f..788cbb9fd53 100644 --- a/test/langtools/tools/javac/OverrideChecks/InconsistentReturn.out +++ b/test/langtools/tools/javac/OverrideChecks/InconsistentReturn.out @@ -1,2 +1,2 @@ -InconsistentReturn.java:17:1: compiler.err.types.incompatible.diff.ret: I2, I1, f() +InconsistentReturn.java:17:1: compiler.err.types.incompatible: I2, I1, (compiler.misc.incompatible.diff.ret: f, ) 1 error diff --git a/test/langtools/tools/javac/defaultMethods/Neg01.out b/test/langtools/tools/javac/defaultMethods/Neg01.out index ca44ab6bec9..533ff91d83b 100644 --- a/test/langtools/tools/javac/defaultMethods/Neg01.out +++ b/test/langtools/tools/javac/defaultMethods/Neg01.out @@ -1,2 +1,2 @@ -Neg01.java:14:12: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg01.AB, m, , Neg01.IA, Neg01.IB +Neg01.java:14:12: compiler.err.types.incompatible: Neg01.IA, Neg01.IB, (compiler.misc.incompatible.unrelated.defaults: kindname.class, Neg01.AB, m, , Neg01.IA, Neg01.IB) 1 error diff --git a/test/langtools/tools/javac/defaultMethods/Neg02.out b/test/langtools/tools/javac/defaultMethods/Neg02.out index 3fb05ab2adc..8f54fee405c 100644 --- a/test/langtools/tools/javac/defaultMethods/Neg02.out +++ b/test/langtools/tools/javac/defaultMethods/Neg02.out @@ -1,2 +1,2 @@ -Neg02.java:16:13: compiler.err.types.incompatible.unrelated.defaults: kindname.class, Neg02.X, m, , Neg02.A, Neg02.B +Neg02.java:16:13: compiler.err.types.incompatible: Neg02.A, Neg02.B, (compiler.misc.incompatible.unrelated.defaults: kindname.class, Neg02.X, m, , Neg02.A, Neg02.B) 1 error diff --git a/test/langtools/tools/javac/defaultMethods/Neg14.out b/test/langtools/tools/javac/defaultMethods/Neg14.out index 0d595aa7cf4..8267072400f 100644 --- a/test/langtools/tools/javac/defaultMethods/Neg14.out +++ b/test/langtools/tools/javac/defaultMethods/Neg14.out @@ -1,2 +1,2 @@ -Neg14.java:10:14: compiler.err.types.incompatible.abstract.default: kindname.class, Neg14.AB, m, , Neg14.IB, Neg14.IA +Neg14.java:10:14: compiler.err.types.incompatible: Neg14.IB, Neg14.IA, (compiler.misc.incompatible.abstract.default: kindname.class, Neg14.AB, m, , Neg14.IB, Neg14.IA) 1 error diff --git a/test/langtools/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java b/test/langtools/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java index 4873516465d..cce894569c5 100644 --- a/test/langtools/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java +++ b/test/langtools/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.types.incompatible.diff.ret +// key: compiler.err.types.incompatible +// key: compiler.misc.incompatible.diff.ret // key: compiler.err.prob.found.req // key: compiler.misc.incompatible.descs.in.functional.intf // key: compiler.misc.descriptor diff --git a/test/langtools/tools/javac/diags/examples/TypesIncompatible.java b/test/langtools/tools/javac/diags/examples/TypesIncompatible.java index e4197624038..e1795c95f9f 100644 --- a/test/langtools/tools/javac/diags/examples/TypesIncompatible.java +++ b/test/langtools/tools/javac/diags/examples/TypesIncompatible.java @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.types.incompatible.diff.ret +// key: compiler.err.types.incompatible +// key: compiler.misc.incompatible.diff.ret interface A { int m(); diff --git a/test/langtools/tools/javac/diags/examples/TypesIncompatibleAbstractDefault.java b/test/langtools/tools/javac/diags/examples/TypesIncompatibleAbstractDefault.java index d94a88ef7bb..162f8467920 100644 --- a/test/langtools/tools/javac/diags/examples/TypesIncompatibleAbstractDefault.java +++ b/test/langtools/tools/javac/diags/examples/TypesIncompatibleAbstractDefault.java @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.types.incompatible.abstract.default +// key: compiler.err.types.incompatible +// key: compiler.misc.incompatible.abstract.default class TypesIncompatibleAbstractDefault { interface A { diff --git a/test/langtools/tools/javac/diags/examples/TypesIncompatibleUnrelatedDefaults.java b/test/langtools/tools/javac/diags/examples/TypesIncompatibleUnrelatedDefaults.java index 28c75bc644b..c03971abeb1 100644 --- a/test/langtools/tools/javac/diags/examples/TypesIncompatibleUnrelatedDefaults.java +++ b/test/langtools/tools/javac/diags/examples/TypesIncompatibleUnrelatedDefaults.java @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.types.incompatible.unrelated.defaults +// key: compiler.err.types.incompatible +// key: compiler.misc.incompatible.unrelated.defaults class TypesIncompatibleUnrelatedDefaults { interface A { diff --git a/test/langtools/tools/javac/generics/6294779/T6294779c.out b/test/langtools/tools/javac/generics/6294779/T6294779c.out index 244b9f7fffe..7cc14e45eb0 100644 --- a/test/langtools/tools/javac/generics/6294779/T6294779c.out +++ b/test/langtools/tools/javac/generics/6294779/T6294779c.out @@ -1,2 +1,2 @@ -T6294779c.java:29:5: compiler.err.types.incompatible.diff.ret: T6294779c.I2, T6294779c.I1, get() +T6294779c.java:29:5: compiler.err.types.incompatible: T6294779c.I2, T6294779c.I1, (compiler.misc.incompatible.diff.ret: get, ) 1 error diff --git a/test/langtools/tools/javac/generics/abstract/T4717181c.out b/test/langtools/tools/javac/generics/abstract/T4717181c.out index 4ac9fbc1165..aacb51a4bc1 100644 --- a/test/langtools/tools/javac/generics/abstract/T4717181c.out +++ b/test/langtools/tools/javac/generics/abstract/T4717181c.out @@ -1,2 +1,2 @@ -T4717181c.java:15:21: compiler.err.types.incompatible.diff.ret: T4717181c.A, T4717181c.A, f(java.lang.Integer) +T4717181c.java:15:21: compiler.err.types.incompatible: T4717181c.A, T4717181c.A, (compiler.misc.incompatible.diff.ret: f, java.lang.Integer) 1 error diff --git a/test/langtools/tools/javac/generics/rawOverride/7157798/Test3.out b/test/langtools/tools/javac/generics/rawOverride/7157798/Test3.out index 80960df0a78..8426040b22f 100644 --- a/test/langtools/tools/javac/generics/rawOverride/7157798/Test3.out +++ b/test/langtools/tools/javac/generics/rawOverride/7157798/Test3.out @@ -1,6 +1,6 @@ -Test3.java:14:1: compiler.err.types.incompatible.diff.ret: B, A, m() -Test3.java:19:1: compiler.err.types.incompatible.diff.ret: D, C, m() -Test3.java:27:1: compiler.err.types.incompatible.diff.ret: E, B, m() -Test3.java:33:1: compiler.err.types.incompatible.diff.ret: F, E, m() -Test3.java:37:1: compiler.err.types.incompatible.diff.ret: F, E, m() +Test3.java:14:1: compiler.err.types.incompatible: B, A, (compiler.misc.incompatible.diff.ret: m, ) +Test3.java:19:1: compiler.err.types.incompatible: D, C, (compiler.misc.incompatible.diff.ret: m, ) +Test3.java:27:1: compiler.err.types.incompatible: E, B, (compiler.misc.incompatible.diff.ret: m, ) +Test3.java:33:1: compiler.err.types.incompatible: F, E, (compiler.misc.incompatible.diff.ret: m, ) +Test3.java:37:1: compiler.err.types.incompatible: F, E, (compiler.misc.incompatible.diff.ret: m, ) 5 errors diff --git a/test/langtools/tools/javac/generics/typevars/4856983/T4856983a.out b/test/langtools/tools/javac/generics/typevars/4856983/T4856983a.out index f359892417f..490167c79fa 100644 --- a/test/langtools/tools/javac/generics/typevars/4856983/T4856983a.out +++ b/test/langtools/tools/javac/generics/typevars/4856983/T4856983a.out @@ -1,2 +1,2 @@ -T4856983a.java:13:6: compiler.err.types.incompatible.diff.ret: I2, I1, m() +T4856983a.java:13:6: compiler.err.types.incompatible: I2, I1, (compiler.misc.incompatible.diff.ret: m, ) 1 error diff --git a/test/langtools/tools/javac/generics/typevars/4856983/T4856983b.out b/test/langtools/tools/javac/generics/typevars/4856983/T4856983b.out index 256af27c696..5f8e361769f 100644 --- a/test/langtools/tools/javac/generics/typevars/4856983/T4856983b.out +++ b/test/langtools/tools/javac/generics/typevars/4856983/T4856983b.out @@ -1,2 +1,2 @@ -T4856983b.java:12:24: compiler.err.types.incompatible.diff.ret: I2, I1, m() +T4856983b.java:12:24: compiler.err.types.incompatible: I2, I1, (compiler.misc.incompatible.diff.ret: m, ) 1 error diff --git a/test/langtools/tools/javac/generics/typevars/6199146/T6199146.out b/test/langtools/tools/javac/generics/typevars/6199146/T6199146.out index d487e95ab65..99f434fd606 100644 --- a/test/langtools/tools/javac/generics/typevars/6199146/T6199146.out +++ b/test/langtools/tools/javac/generics/typevars/6199146/T6199146.out @@ -1,2 +1,2 @@ -T6199146.java:9:25: compiler.err.types.incompatible.diff.ret: T6199146.I2, T6199146.I1, getFoo() +T6199146.java:9:25: compiler.err.types.incompatible: T6199146.I2, T6199146.I1, (compiler.misc.incompatible.diff.ret: getFoo, ) 1 error diff --git a/test/langtools/tools/javac/generics/wildcards/7034495/T7034495.out b/test/langtools/tools/javac/generics/wildcards/7034495/T7034495.out index 58aa1f67616..59ac8fbfa1d 100644 --- a/test/langtools/tools/javac/generics/wildcards/7034495/T7034495.out +++ b/test/langtools/tools/javac/generics/wildcards/7034495/T7034495.out @@ -1,2 +1,2 @@ -T7034495.java:40:17: compiler.err.types.incompatible.diff.ret: T7034495.B, T7034495.A, foo() +T7034495.java:40:17: compiler.err.types.incompatible: T7034495.B, T7034495.A, (compiler.misc.incompatible.diff.ret: foo, ) 1 error diff --git a/test/langtools/tools/javac/lambda/BadConv04.out b/test/langtools/tools/javac/lambda/BadConv04.out index 4eae22a993a..0978ee9b3f8 100644 --- a/test/langtools/tools/javac/lambda/BadConv04.out +++ b/test/langtools/tools/javac/lambda/BadConv04.out @@ -1,3 +1,3 @@ -BadConv04.java:19:5: compiler.err.types.incompatible.diff.ret: BadConv04.I2, BadConv04.I1, m() +BadConv04.java:19:5: compiler.err.types.incompatible: BadConv04.I2, BadConv04.I1, (compiler.misc.incompatible.diff.ret: m, ) BadConv04.java:21:13: compiler.err.prob.found.req: (compiler.misc.incompatible.descs.in.functional.intf: kindname.interface, BadConv04.SAM,{(compiler.misc.descriptor: m, , long, ),(compiler.misc.descriptor: m, , int, )}) 2 errors diff --git a/test/langtools/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java b/test/langtools/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java index 9d6913edf5f..a4be15d320b 100644 --- a/test/langtools/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java +++ b/test/langtools/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java @@ -1001,18 +1001,18 @@ public class BridgeMethodsTemplateTest extends BridgeMethodTestCase { public void testA5() throws IOException, ReflectiveOperationException { compileSpec("C(A(Id0),Jd0)", - "compiler.err.types.incompatible.unrelated.defaults"); + "compiler.err.types.incompatible"); } public void testA6() throws IOException, ReflectiveOperationException { compileSpec("C(A(Ia0,Jd0))", "compiler.err.does.not.override.abstract", - "compiler.err.types.incompatible.abstract.default"); + "compiler.err.types.incompatible"); } public void testA7() throws IOException, ReflectiveOperationException { compileSpec("C(A(Id0,Jd0))", - "compiler.err.types.incompatible.unrelated.defaults"); + "compiler.err.types.incompatible"); } public void testA8() throws IOException, ReflectiveOperationException { diff --git a/test/langtools/tools/javac/lambda/funcInterfaces/NonSAM2.out b/test/langtools/tools/javac/lambda/funcInterfaces/NonSAM2.out index 8360f7c4475..7e3df37f96b 100644 --- a/test/langtools/tools/javac/lambda/funcInterfaces/NonSAM2.out +++ b/test/langtools/tools/javac/lambda/funcInterfaces/NonSAM2.out @@ -1,4 +1,4 @@ -NonSAM2.java:13:1: compiler.err.types.incompatible.diff.ret: Bar1, Foo1, getAge(java.lang.String) +NonSAM2.java:13:1: compiler.err.types.incompatible: Bar1, Foo1, (compiler.misc.incompatible.diff.ret: getAge, java.lang.String) NonSAM2.java:15:1: compiler.err.name.clash.same.erasure.no.override: getOldest, java.util.List, C, getOldest, java.util.List, A NonSAM2.java:17:1: compiler.err.name.clash.same.erasure.no.override: getOldest, java.util.List, D, getOldest, java.util.List, A NonSAM2.java:21:1: compiler.err.name.clash.same.erasure.no.override: m, T2, Bar2, m, T1, Foo2 diff --git a/test/langtools/tools/javac/miranda/4711056/T1.out b/test/langtools/tools/javac/miranda/4711056/T1.out index b9edac1ee51..af4b8f906d9 100644 --- a/test/langtools/tools/javac/miranda/4711056/T1.out +++ b/test/langtools/tools/javac/miranda/4711056/T1.out @@ -1,2 +1,2 @@ -T4.java:3:10: compiler.err.types.incompatible.diff.ret: iclss01004_2, iclss01004_1, foo(int) +T4.java:3:10: compiler.err.types.incompatible: iclss01004_2, iclss01004_1, (compiler.misc.incompatible.diff.ret: foo, int) 1 error From c4f1bb00198ed09fa2c31076ce812331310730a5 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 20 Dec 2017 08:05:04 -0800 Subject: [PATCH 11/25] 8193842: Replace Files.copy(InputStream,OutputStream) with InputStream.transferTo(OutputStream) Reviewed-by: clanger, alanb --- .../share/classes/java/nio/file/Files.java | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index c7e0dcf9938..41ac57fa3cf 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -2954,22 +2954,6 @@ public final class Files { return newBufferedWriter(path, StandardCharsets.UTF_8, options); } - /** - * Reads all bytes from an input stream and writes them to an output stream. - */ - private static long copy(InputStream source, OutputStream sink) - throws IOException - { - long nread = 0L; - byte[] buf = new byte[BUFFER_SIZE]; - int n; - while ((n = source.read(buf)) > 0) { - sink.write(buf, 0, n); - nread += n; - } - return nread; - } - /** * Copies all bytes from an input stream to a file. On return, the input * stream will be at end of stream. @@ -3082,7 +3066,7 @@ public final class Files { // do the copy try (OutputStream out = ostream) { - return copy(in, out); + return in.transferTo(out); } } @@ -3124,7 +3108,7 @@ public final class Files { Objects.requireNonNull(out); try (InputStream in = newInputStream(source)) { - return copy(in, out); + return in.transferTo(out); } } From 3851e0e0308ab300153706646cba48edd24faf98 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Wed, 20 Dec 2017 17:36:50 +0100 Subject: [PATCH 12/25] 8193371: Use Dynalink REMOVE operation in Nashorn Reviewed-by: hannesw, sundar --- .../dynalink/beans/AbstractJavaLinker.java | 27 +-- .../jdk/dynalink/beans/BeanLinker.java | 25 +- .../internal/codegen/AssignSymbols.java | 64 +----- .../internal/codegen/CodeGenerator.java | 54 +++++ .../codegen/LocalVariableTypesCalculator.java | 19 +- .../internal/codegen/MethodEmitter.java | 66 +++++- .../jdk/nashorn/internal/ir/RuntimeNode.java | 6 - .../internal/runtime/ScriptObject.java | 12 + .../internal/runtime/ScriptRuntime.java | 87 ++----- .../nashorn/internal/runtime/Undefined.java | 15 ++ .../runtime/linker/JSObjectLinker.java | 26 ++- .../runtime/linker/NashornBottomLinker.java | 42 +++- .../linker/NashornCallSiteDescriptor.java | 47 ++-- test/nashorn/script/basic/JDK-8193371.js | 215 ++++++++++++++++++ .../script/basic/JDK-8193371.js.EXPECTED | 6 + 15 files changed, 523 insertions(+), 188 deletions(-) create mode 100644 test/nashorn/script/basic/JDK-8193371.js create mode 100644 test/nashorn/script/basic/JDK-8193371.js.EXPECTED diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java index f648a81f0ca..bc5c0645588 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java @@ -414,20 +414,21 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception { - if (!req.namespaces.isEmpty()) { - final Namespace ns = req.namespaces.get(0); - final Operation op = req.baseOperation; - if (op == StandardOperation.GET) { - if (ns == StandardNamespace.PROPERTY) { - return getPropertyGetter(req.popNamespace()); - } else if (ns == StandardNamespace.METHOD) { - return getMethodGetter(req.popNamespace()); - } - } else if (op == StandardOperation.SET && ns == StandardNamespace.PROPERTY) { - return getPropertySetter(req.popNamespace()); - } + if (req.namespaces.isEmpty()) { + return null; } - return null; + final Namespace ns = req.namespaces.get(0); + final Operation op = req.baseOperation; + if (op == StandardOperation.GET) { + if (ns == StandardNamespace.PROPERTY) { + return getPropertyGetter(req.popNamespace()); + } else if (ns == StandardNamespace.METHOD) { + return getMethodGetter(req.popNamespace()); + } + } else if (op == StandardOperation.SET && ns == StandardNamespace.PROPERTY) { + return getPropertySetter(req.popNamespace()); + } + return getNextComponent(req.popNamespace()); } GuardedInvocationComponent getNextComponent(final ComponentLinkRequest req) throws Exception { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java index cff9cc12df6..d46bd105b67 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java @@ -136,24 +136,21 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL @Override protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception { - final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(req); - if(superGic != null) { - return superGic; + if (req.namespaces.isEmpty()) { + return null; } - if (!req.namespaces.isEmpty()) { + final Namespace ns = req.namespaces.get(0); + if (ns == StandardNamespace.ELEMENT) { final Operation op = req.baseOperation; - final Namespace ns = req.namespaces.get(0); - if (ns == StandardNamespace.ELEMENT) { - if (op == StandardOperation.GET) { - return getElementGetter(req.popNamespace()); - } else if (op == StandardOperation.SET) { - return getElementSetter(req.popNamespace()); - } else if (op == StandardOperation.REMOVE) { - return getElementRemover(req.popNamespace()); - } + if (op == StandardOperation.GET) { + return getElementGetter(req.popNamespace()); + } else if (op == StandardOperation.SET) { + return getElementSetter(req.popNamespace()); + } else if (op == StandardOperation.REMOVE) { + return getElementRemover(req.popNamespace()); } } - return null; + return super.getGuardedInvocationComponent(req); } @Override diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java index 7d37330dd88..f01c7f9c259 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java @@ -59,6 +59,7 @@ import java.util.ListIterator; import java.util.Map; import java.util.Set; import jdk.nashorn.internal.ir.AccessNode; +import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.CatchNode; @@ -735,72 +736,13 @@ final class AssignSymbols extends SimpleNodeVisitor implements Loggable { @Override public Node leaveUnaryNode(final UnaryNode unaryNode) { - switch (unaryNode.tokenType()) { - case DELETE: - return leaveDELETE(unaryNode); - case TYPEOF: + if (unaryNode.tokenType() == TokenType.TYPEOF) { return leaveTYPEOF(unaryNode); - default: + } else { return super.leaveUnaryNode(unaryNode); } } - private Node leaveDELETE(final UnaryNode unaryNode) { - final FunctionNode currentFunctionNode = lc.getCurrentFunction(); - final boolean strictMode = currentFunctionNode.isStrict(); - final Expression rhs = unaryNode.getExpression(); - final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this); - - Request request = Request.DELETE; - final List args = new ArrayList<>(); - - if (rhs instanceof IdentNode) { - final IdentNode ident = (IdentNode)rhs; - // If this is a declared variable or a function parameter, delete always fails (except for globals). - final String name = ident.getName(); - final Symbol symbol = ident.getSymbol(); - - if (symbol.isThis()) { - // Can't delete "this", ignore and return true - return LiteralNode.newInstance(unaryNode, true); - } - final Expression literalNode = LiteralNode.newInstance(unaryNode, name); - final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); - - if (!failDelete) { - args.add(compilerConstantIdentifier(SCOPE)); - } - args.add(literalNode); - args.add(strictFlagNode); - - if (failDelete) { - request = Request.FAIL_DELETE; - } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) { - request = Request.SLOW_DELETE; - } - } else if (rhs instanceof AccessNode) { - final Expression base = ((AccessNode)rhs).getBase(); - final String property = ((AccessNode)rhs).getProperty(); - - args.add(base); - args.add(LiteralNode.newInstance(unaryNode, property)); - args.add(strictFlagNode); - - } else if (rhs instanceof IndexNode) { - final IndexNode indexNode = (IndexNode)rhs; - final Expression base = indexNode.getBase(); - final Expression index = indexNode.getIndex(); - - args.add(base); - args.add(index); - args.add(strictFlagNode); - - } else { - throw new AssertionError("Unexpected delete with " + rhs.getClass().getName() + " expression"); - } - return new RuntimeNode(unaryNode, request, args); - } - @Override public Node leaveForNode(final ForNode forNode) { if (forNode.isForInOrOf()) { diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java index 43074a2c735..20669563256 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -151,6 +151,7 @@ import jdk.nashorn.internal.runtime.Undefined; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; @@ -1141,6 +1142,12 @@ final class CodeGenerator extends NodeOperatorVisitor LARGE_STRING_THRESHOLD) { // use removeIndex for extremely long names + return load(name).dynamicRemoveIndex(flags); + } + + debug("dynamic_remove", name, Type.BOOLEAN, getProgramPoint(flags)); + + popType(Type.OBJECT); + // Type is widened to OBJECT then coerced back to BOOLEAN + method.visitInvokeDynamicInsn(NameCodec.encode(name), + Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT), LINKERBOOTSTRAP, flags | dynRemoveOperation(isIndex)); + + pushType(Type.OBJECT); + convert(Type.BOOLEAN); //most probably a nop + + return this; + } + + /** * Dynamic getter for indexed structures. Pop index and receiver from stack, * generate appropriate signatures based on types * @@ -2341,6 +2366,35 @@ public class MethodEmitter { LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.SET_ELEMENT); } + /** + * Dynamic remover for indexed structures. Pop index and receiver from stack, + * generate appropriate signatures based on types + * + * @param flags call site flags for getter + * + * @return the method emitter + */ + MethodEmitter dynamicRemoveIndex(final int flags) { + debug("dynamic_remove_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags)); + + Type index = peekType(); + if (index.isObject() || index.isBoolean()) { + index = Type.OBJECT; //e.g. string->object + convert(Type.OBJECT); + } + popType(); + + popType(Type.OBJECT); + + final String signature = Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT /*e.g STRING->OBJECT*/, index); + + method.visitInvokeDynamicInsn(EMPTY_NAME, signature, LINKERBOOTSTRAP, flags | dynRemoveOperation(true)); + pushType(Type.OBJECT); + convert(Type.BOOLEAN); + + return this; + } + /** * Load a key value in the proper form. * @@ -2520,6 +2574,10 @@ public class MethodEmitter { return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY; } + private static int dynRemoveOperation(final boolean isIndex) { + return isIndex ? NashornCallSiteDescriptor.REMOVE_ELEMENT : NashornCallSiteDescriptor.REMOVE_PROPERTY; + } + private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) { final Type from = conversion.getFrom(); final Type to = conversion.getTo(); diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java index 76a9253ce30..afc52bf3f9a 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java @@ -54,12 +54,6 @@ public class RuntimeNode extends Expression { TYPEOF, /** Reference error type */ REFERENCE_ERROR, - /** Delete operator */ - DELETE(TokenType.DELETE, Type.BOOLEAN, 1), - /** Delete operator for slow scopes */ - SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), - /** Delete operator that always fails -- see Lower */ - FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** === operator with at least one object */ EQ_STRICT(TokenType.EQ_STRICT, Type.BOOLEAN, 2, true), /** == operator with at least one object */ diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java index 40b8c67d9a6..3431a4ff8f8 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java @@ -189,6 +189,8 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { /** Method handle for generic property setter */ public static final Call GENERIC_SET = virtualCallNoLookup(ScriptObject.class, "set", void.class, Object.class, Object.class, int.class); + public static final Call DELETE = virtualCall(MethodHandles.lookup(), ScriptObject.class, "delete", boolean.class, Object.class, boolean.class); + static final MethodHandle[] SET_SLOW = new MethodHandle[] { findOwnMH_V("set", void.class, Object.class, int.class, int.class), findOwnMH_V("set", void.class, Object.class, double.class, int.class), @@ -202,6 +204,9 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { static final MethodHandle EXTENSION_CHECK = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class); static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class); + private static final GuardedInvocation DELETE_GUARDED = new GuardedInvocation(MH.insertArguments(DELETE.methodHandle(), 2, false), NashornGuards.getScriptObjectGuard()); + private static final GuardedInvocation DELETE_GUARDED_STRICT = new GuardedInvocation(MH.insertArguments(DELETE.methodHandle(), 2, true), NashornGuards.getScriptObjectGuard()); + /** * Constructor */ @@ -1869,6 +1874,13 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { return desc.getOperation() instanceof NamedOperation ? findSetMethod(desc, request) : findSetIndexMethod(desc, request); + case REMOVE: + final GuardedInvocation inv = NashornCallSiteDescriptor.isStrict(desc) ? DELETE_GUARDED_STRICT : DELETE_GUARDED; + final Object name = NamedOperation.getName(desc.getOperation()); + if (name != null) { + return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard()); + } + return inv; case CALL: return findCallMethod(desc, request); case NEW: diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java index 8a914ddfd03..d82e03bb92e 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java @@ -135,6 +135,16 @@ public final class ScriptRuntime { */ public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class); + /** + * Used to perform failed delete under strict mode + */ + public static final Call STRICT_FAIL_DELETE = staticCallNoLookup(ScriptRuntime.class, "strictFailDelete", boolean.class, String.class); + + /** + * Used to find the scope for slow delete + */ + public static final Call SLOW_DELETE = staticCallNoLookup(ScriptRuntime.class, "slowDelete", boolean.class, ScriptObject.class, String.class); + /** * Converts a switch tag value to a simple integer. deflt value if it can't. * @@ -779,88 +789,41 @@ public final class ScriptRuntime { throw referenceError("cant.be.used.as.lhs", Objects.toString(msg)); } - /** - * ECMA 11.4.1 - delete operation, generic implementation - * - * @param obj object with property to delete - * @param property property to delete - * @param strict are we in strict mode - * - * @return true if property was successfully found and deleted - */ - public static boolean DELETE(final Object obj, final Object property, final Object strict) { - if (obj instanceof ScriptObject) { - return ((ScriptObject)obj).delete(property, Boolean.TRUE.equals(strict)); - } - - if (obj instanceof Undefined) { - return ((Undefined)obj).delete(property, false); - } - - if (obj == null) { - throw typeError("cant.delete.property", safeToString(property), "null"); - } - - if (obj instanceof ScriptObjectMirror) { - return ((ScriptObjectMirror)obj).delete(property); - } - - if (JSType.isPrimitive(obj)) { - return ((ScriptObject) JSType.toScriptObject(obj)).delete(property, Boolean.TRUE.equals(strict)); - } - - if (obj instanceof JSObject) { - ((JSObject)obj).removeMember(Objects.toString(property)); - return true; - } - - // if object is not reference type, vacuously delete is successful. - return true; - } - /** * ECMA 11.4.1 - delete operator, implementation for slow scopes * * This implementation of 'delete' walks the scope chain to find the scope that contains the - * property to be deleted, then invokes delete on it. + * property to be deleted, then invokes delete on it. Always used on scopes, never strict. * * @param obj top scope object * @param property property to delete - * @param strict are we in strict mode * * @return true if property was successfully found and deleted */ - public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) { - if (obj instanceof ScriptObject) { - ScriptObject sobj = (ScriptObject) obj; - final String key = property.toString(); - while (sobj != null && sobj.isScope()) { - final FindProperty find = sobj.findProperty(key, false); - if (find != null) { - return sobj.delete(key, Boolean.TRUE.equals(strict)); - } - sobj = sobj.getProto(); + public static boolean slowDelete(final ScriptObject obj, final String property) { + ScriptObject sobj = obj; + while (sobj != null && sobj.isScope()) { + final FindProperty find = sobj.findProperty(property, false); + if (find != null) { + return sobj.delete(property, false); } + sobj = sobj.getProto(); } - return DELETE(obj, property, strict); + return obj.delete(property, false); } /** * ECMA 11.4.1 - delete operator, special case * - * This is 'delete' that always fails. We have to check strict mode and throw error. - * That is why this is a runtime function. Or else we could have inlined 'false'. + * This is 'delete' on a scope; it always fails under strict mode. + * It always throws an exception, but is declared to return a boolean + * to be compatible with the delete operator type. * * @param property property to delete - * @param strict are we in strict mode - * - * @return false always + * @return nothing, always throws an exception. */ - public static boolean FAIL_DELETE(final Object property, final Object strict) { - if (Boolean.TRUE.equals(strict)) { - throw syntaxError("strict.cant.delete", safeToString(property)); - } - return false; + public static boolean strictFailDelete(final String property) { + throw syntaxError("strict.cant.delete", property); } /** diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java index 48a9f9251b4..5cb460d76f1 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java @@ -112,6 +112,11 @@ public final class Undefined extends DefaultPropertyAccess { return findSetIndexMethod(desc); } return findSetMethod(desc); + case REMOVE: + if (!(desc.getOperation() instanceof NamedOperation)) { + return findDeleteIndexMethod(desc); + } + return findDeleteMethod(desc); default: } return null; @@ -124,6 +129,7 @@ public final class Undefined extends DefaultPropertyAccess { private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class); private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, int.class), 3, NashornCallSiteDescriptor.CALLSITE_STRICT); + private static final MethodHandle DELETE_METHOD = MH.insertArguments(findOwnMH("delete", boolean.class, Object.class, boolean.class), 2, false); private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) { return new GuardedInvocation(MH.insertArguments(GET_METHOD, 1, NashornCallSiteDescriptor.getOperand(desc)), UNDEFINED_GUARD).asType(desc); @@ -141,6 +147,15 @@ public final class Undefined extends DefaultPropertyAccess { return new GuardedInvocation(SET_METHOD, UNDEFINED_GUARD).asType(desc); } + private static GuardedInvocation findDeleteMethod(final CallSiteDescriptor desc) { + return new GuardedInvocation(MH.insertArguments(DELETE_METHOD, 1, NashornCallSiteDescriptor.getOperand(desc)), UNDEFINED_GUARD).asType(desc); + } + + private static GuardedInvocation findDeleteIndexMethod(final CallSiteDescriptor desc) { + return new GuardedInvocation(DELETE_METHOD, UNDEFINED_GUARD).asType(desc); + } + + @Override public Object get(final Object key) { throw typeError("cant.read.property.of.undefined", ScriptRuntime.safeToString(key)); diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java index 1200ebba363..eeb6edd3dd9 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java @@ -31,7 +31,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Map; -import javax.script.Bindings; +import java.util.Objects; import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.Operation; import jdk.dynalink.StandardOperation; @@ -64,11 +64,10 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { return canLinkTypeStatic(type); } - static boolean canLinkTypeStatic(final Class type) { - // can link JSObject also handles Map, Bindings to make + private static boolean canLinkTypeStatic(final Class type) { + // can link JSObject also handles Map (this includes Bindings) to make // sure those are not JSObjects. return Map.class.isAssignableFrom(type) || - Bindings.class.isAssignableFrom(type) || JSObject.class.isAssignableFrom(type); } @@ -84,7 +83,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { if (self instanceof JSObject) { inv = lookup(desc, request, linkerServices); inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard()); - } else if (self instanceof Map || self instanceof Bindings) { + } else if (self instanceof Map) { // guard to make sure the Map or Bindings does not turn into JSObject later! final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); inv = new GuardedInvocation(beanInv.getInvocation(), @@ -116,6 +115,13 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { return name != null ? findSetMethod(name) : findSetIndexMethod(); } break; + case REMOVE: + if (NashornCallSiteDescriptor.hasStandardNamespace(desc)) { + return new GuardedInvocation( + name == null ? JSOBJECTLINKER_DEL : MH.insertArguments(JSOBJECTLINKER_DEL, 1, name), + IS_JSOBJECT_GUARD); + } + break; case CALL: return findCallMethod(desc); case NEW: @@ -206,6 +212,15 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { } } + @SuppressWarnings("unused") + private static boolean del(final Object jsobj, final Object key) { + if (jsobj instanceof ScriptObjectMirror) { + return ((ScriptObjectMirror)jsobj).delete(key); + } + ((JSObject) jsobj).removeMember(Objects.toString(key)); + return true; + } + private static int getIndex(final Number n) { final double value = n.doubleValue(); return JSType.isRepresentableAsInt(value) ? (int)value : -1; @@ -245,6 +260,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH_S("isJSObject", boolean.class, Object.class); private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class); private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_DEL = findOwnMH_S("del", boolean.class, Object.class, Object.class); // method handles of JSObject class private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class); diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java index bd4ab24fe27..481919317ad 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java @@ -39,11 +39,13 @@ import jdk.dynalink.CallSiteDescriptor; import jdk.dynalink.NamedOperation; import jdk.dynalink.Operation; import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; import jdk.dynalink.linker.GuardedInvocation; import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.GuardingTypeConverterFactory; import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.ECMAException; @@ -86,12 +88,16 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class); private static final MethodHandle THROW_STRICT_PROPERTY_SETTER; + private static final MethodHandle THROW_STRICT_PROPERTY_REMOVER; private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED; + private static final MethodHandle MISSING_PROPERTY_REMOVER; static { final Lookup lookup = new Lookup(MethodHandles.lookup()); THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class); + THROW_STRICT_PROPERTY_REMOVER = lookup.findOwnStatic("throwStrictPropertyRemover", boolean.class, Object.class, Object.class); THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class); + MISSING_PROPERTY_REMOVER = lookup.findOwnStatic("missingPropertyRemover", boolean.class, Object.class, Object.class); } private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception { @@ -124,6 +130,7 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); final String operand = NashornCallSiteDescriptor.getOperand(desc); + final boolean strict = NashornCallSiteDescriptor.isStrict(desc); switch (NashornCallSiteDescriptor.getStandardOperation(desc)) { case GET: if (NashornCallSiteDescriptor.isOptimistic(desc)) { @@ -133,13 +140,17 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo } return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc); case SET: - final boolean strict = NashornCallSiteDescriptor.isStrict(desc); if (strict) { return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc); } else if (operand != null) { return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc); } return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc); + case REMOVE: + if (strict) { + return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_REMOVER, operand), desc); + } + return getInvocation(bindOperand(MISSING_PROPERTY_REMOVER, operand), linkerServices, desc); default: throw new AssertionError("unknown call type " + desc); } @@ -162,6 +173,33 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo throw createTypeError(self, name, "cant.set.property"); } + @SuppressWarnings("unused") + private static boolean throwStrictPropertyRemover(final Object self, final Object name) { + if (isNonConfigurableProperty(self, name)) { + throw createTypeError(self, name, "cant.delete.property"); + } + return true; + } + + @SuppressWarnings("unused") + private static boolean missingPropertyRemover(final Object self, final Object name) { + return !isNonConfigurableProperty(self, name); + } + + // Corresponds to ECMAScript 5.1 8.12.7 [[Delete]] point 3 check for "isConfigurable" (but negated) + private static boolean isNonConfigurableProperty(final Object self, final Object name) { + if (self instanceof StaticClass) { + final Class clazz = ((StaticClass)self).getRepresentedClass(); + return BeansLinker.getReadableStaticPropertyNames(clazz).contains(name) || + BeansLinker.getWritableStaticPropertyNames(clazz).contains(name) || + BeansLinker.getStaticMethodNames(clazz).contains(name); + } + final Class clazz = self.getClass(); + return BeansLinker.getReadableInstancePropertyNames(clazz).contains(name) || + BeansLinker.getWritableInstancePropertyNames(clazz).contains(name) || + BeansLinker.getInstanceMethodNames(clazz).contains(name); + } + private static ECMAException createTypeError(final Object self, final Object name, final String msg) { return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self)); } @@ -215,6 +253,8 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null"); case SET: throw typeError("cant.set.property", getArgument(linkRequest), "null"); + case REMOVE: + throw typeError("cant.delete.property", getArgument(linkRequest), "null"); default: throw new AssertionError("unknown call type " + desc); } diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java index f01faa921a8..28db284c0ca 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java @@ -29,6 +29,7 @@ import static jdk.dynalink.StandardNamespace.ELEMENT; import static jdk.dynalink.StandardNamespace.METHOD; import static jdk.dynalink.StandardNamespace.PROPERTY; import static jdk.dynalink.StandardOperation.GET; +import static jdk.dynalink.StandardOperation.REMOVE; import static jdk.dynalink.StandardOperation.SET; import java.lang.invoke.MethodHandles; @@ -63,7 +64,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; * form of static methods. */ public final class NashornCallSiteDescriptor extends CallSiteDescriptor { - // Lowest three bits describe the operation + // Lowest four bits describe the operation /** Property getter operation {@code obj.prop} */ public static final int GET_PROPERTY = 0; /** Element getter operation {@code obj[index]} */ @@ -76,12 +77,16 @@ public final class NashornCallSiteDescriptor extends CallSiteDescriptor { public static final int SET_PROPERTY = 4; /** Element setter operation {@code obj[index] = value} */ public static final int SET_ELEMENT = 5; + /** Property remove operation {@code delete obj.prop} */ + public static final int REMOVE_PROPERTY = 6; + /** Element remove operation {@code delete obj[index]} */ + public static final int REMOVE_ELEMENT = 7; /** Call operation {@code fn(args...)} */ - public static final int CALL = 6; + public static final int CALL = 8; /** New operation {@code new Constructor(args...)} */ - public static final int NEW = 7; + public static final int NEW = 9; - private static final int OPERATION_MASK = 7; + private static final int OPERATION_MASK = 15; // Correspond to the operation indices above. private static final Operation[] OPERATIONS = new Operation[] { @@ -91,42 +96,44 @@ public final class NashornCallSiteDescriptor extends CallSiteDescriptor { GET.withNamespaces(METHOD, ELEMENT, PROPERTY), SET.withNamespaces(PROPERTY, ELEMENT), SET.withNamespaces(ELEMENT, PROPERTY), + REMOVE.withNamespaces(PROPERTY, ELEMENT), + REMOVE.withNamespaces(ELEMENT, PROPERTY), StandardOperation.CALL, StandardOperation.NEW }; /** Flags that the call site references a scope variable (it's an identifier reference or a var declaration, not a * property access expression. */ - public static final int CALLSITE_SCOPE = 1 << 3; + public static final int CALLSITE_SCOPE = 1 << 4; /** Flags that the call site is in code that uses ECMAScript strict mode. */ - public static final int CALLSITE_STRICT = 1 << 4; + public static final int CALLSITE_STRICT = 1 << 5; /** Flags that a property getter or setter call site references a scope variable that is located at a known distance * in the scope chain. Such getters and setters can often be linked more optimally using these assumptions. */ - public static final int CALLSITE_FAST_SCOPE = 1 << 5; + public static final int CALLSITE_FAST_SCOPE = 1 << 6; /** Flags that a callsite type is optimistic, i.e. we might get back a wider return value than encoded in the * descriptor, and in that case we have to throw an UnwarrantedOptimismException */ - public static final int CALLSITE_OPTIMISTIC = 1 << 6; + public static final int CALLSITE_OPTIMISTIC = 1 << 7; /** Is this really an apply that we try to call as a call? */ - public static final int CALLSITE_APPLY_TO_CALL = 1 << 7; + public static final int CALLSITE_APPLY_TO_CALL = 1 << 8; /** Does this a callsite for a variable declaration? */ - public static final int CALLSITE_DECLARE = 1 << 8; + public static final int CALLSITE_DECLARE = 1 << 9; /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit * code where call sites have this flag set. */ - public static final int CALLSITE_PROFILE = 1 << 9; + public static final int CALLSITE_PROFILE = 1 << 10; /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where * call sites have this flag set. */ - public static final int CALLSITE_TRACE = 1 << 10; + public static final int CALLSITE_TRACE = 1 << 11; /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ - public static final int CALLSITE_TRACE_MISSES = 1 << 11; + public static final int CALLSITE_TRACE_MISSES = 1 << 12; /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ - public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 12; + public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 13; /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites * have this flag set. */ - public static final int CALLSITE_TRACE_VALUES = 1 << 13; + public static final int CALLSITE_TRACE_VALUES = 1 << 14; //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious //right now given the program points @@ -138,10 +145,10 @@ public final class NashornCallSiteDescriptor extends CallSiteDescriptor { * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its * trace/profile settings. */ - public static final int CALLSITE_PROGRAM_POINT_SHIFT = 14; + public static final int CALLSITE_PROGRAM_POINT_SHIFT = 15; /** - * Maximum program point value. We have 18 bits left over after flags, and + * Maximum program point value. We have 17 bits left over after flags, and * it should be plenty. Program points are local to a single function. Every * function maps to a single JVM bytecode method that can have at most 65535 * bytes. (Large functions are synthetically split into smaller functions.) @@ -222,8 +229,10 @@ public final class NashornCallSiteDescriptor extends CallSiteDescriptor { case 3: return "GET_METHOD_ELEMENT"; case 4: return "SET_PROPERTY"; case 5: return "SET_ELEMENT"; - case 6: return "CALL"; - case 7: return "NEW"; + case 6: return "REMOVE_PROPERTY"; + case 7: return "REMOVE_ELEMENT"; + case 8: return "CALL"; + case 9: return "NEW"; default: throw new AssertionError(); } } diff --git a/test/nashorn/script/basic/JDK-8193371.js b/test/nashorn/script/basic/JDK-8193371.js new file mode 100644 index 00000000000..615aa872df7 --- /dev/null +++ b/test/nashorn/script/basic/JDK-8193371.js @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2017 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-8193371: Use Dynalink REMOVE operation in Nashorn + * + * @test + * @run + */ + +// This test exercises new functionality enabled by the issue, namely removal of elements from Java lists and maps. + +var ArrayList = java.util.ArrayList; +var HashMap = java.util.HashMap; +var listOf = java.util.List.of; +var mapOf = java.util.Map.of; + +// Remove from a list +(function() { + var a = new ArrayList(listOf("foo", "bar", "baz")); + Assert.assertFalse(delete a.add); + + // Delete actual element + Assert.assertTrue(delete a[1]); + Assert.assertEquals(a, listOf("foo", "baz")); + + // Gracefully ignore silly indices + Assert.assertTrue(delete a[5]); + Assert.assertTrue(delete a[-1]); + Assert.assertTrue(delete a["whatever"]); + Assert.assertTrue(delete a.whatever); + + // Gracefully ignore attempts at deleting methods and properties + Assert.assertFalse(delete a.add); + Assert.assertFalse(delete a.class); + + Assert.assertEquals(a, listOf("foo", "baz")); + + print("List passed.") +})(); + +// Remove from a list, strict +(function() { + "use strict"; + + var a = new ArrayList(listOf("foo", "bar", "baz")); + + // Delete actual element + Assert.assertTrue(delete a[1]); + Assert.assertEquals(a, listOf("foo", "baz")); + + // Gracefully ignore silly indices + Assert.assertTrue(delete a[5]); + Assert.assertTrue(delete a[-1]); + Assert.assertTrue(delete a["whatever"]); + Assert.assertTrue(delete a.whatever); + + // Fail deleting methods and properties + try { delete a.add; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + try { delete a.class; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + + Assert.assertEquals(a, listOf("foo", "baz")); + + print("Strict list passed.") +})(); + +// Remove from a map +(function() { + var m = new HashMap(mapOf("a", 1, "b", 2, "c", 3)); + + // Delete actual elements + Assert.assertTrue(delete m.a); + Assert.assertEquals(m, mapOf("b", 2, "c", 3)); + var key = "b" + Assert.assertTrue(delete m[key]); + Assert.assertEquals(m, mapOf("c", 3)); + + // Gracefully ignore silly indices + Assert.assertTrue(delete m.x); + Assert.assertTrue(delete m[5]); + Assert.assertTrue(delete m[-1]); + Assert.assertTrue(delete m["whatever"]); + + // Gracefully ignore attempts at deleting methods and properties + Assert.assertFalse(delete m.put); + Assert.assertFalse(delete m.class); + + Assert.assertEquals(m, mapOf("c", 3)); + print("Map passed.") +})(); + +// Remove from a map, strict +(function() { + "use strict"; + + var m = new HashMap(mapOf("a", 1, "b", 2, "c", 3)); + + // Delete actual elements + Assert.assertTrue(delete m.a); + Assert.assertEquals(m, mapOf("b", 2, "c", 3)); + var key = "b" + Assert.assertTrue(delete m[key]); + Assert.assertEquals(m, mapOf("c", 3)); + + // Gracefully ignore silly indices + Assert.assertTrue(delete m.x); + Assert.assertTrue(delete m[5]); + Assert.assertTrue(delete m[-1]); + Assert.assertTrue(delete m["whatever"]); + + // Fail deleting methods and properties + try { delete m.size; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + try { delete m.class; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + + // Somewhat counterintuitive, but if we define an element of a map, we can + // delete it, however then the method surfaces, and we can't delete that. + m.size = 4 + Assert.assertTrue(delete m.size) + try { delete m.size; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + + Assert.assertEquals(m, mapOf("c", 3)); + + print("Strict map passed.") +})(); + +// Remove from arrays and beans +(function() { + var a = new (Java.type("int[]"))(2) + a[0] = 42 + a[1] = 13 + + // Huh, Dynalink doesn't expose .clone() on Java arrays? + var c = new (Java.type("int[]"))(2) + c[0] = 42 + c[1] = 13 + + // passes vacuously, but does nothing + Assert.assertTrue(delete a[0]) + Assert.assertEquals(a, c); + + var b = new java.util.BitSet() + b.set(2) + // does nothing + Assert.assertFalse(delete b.get) + // Method is still there and operational + Assert.assertTrue(b.get(2)) + + // passes vacuously for non-existant property + Assert.assertTrue(delete b.foo) + + // statics + var Calendar = java.util.Calendar + Assert.assertFalse(delete Calendar.UNDECIMBER) // field + Assert.assertFalse(delete Calendar.availableLocales) // property + Assert.assertFalse(delete Calendar.getInstance) // method + Assert.assertTrue(delete Calendar.BLAH) // no such thing + + print("Beans passed.") +})(); + +// Remove from arrays and beans, strict +(function() { + "use strict"; + + var a = new (Java.type("int[]"))(2) + a[0] = 42 + a[1] = 13 + + var c = new (Java.type("int[]"))(2) + c[0] = 42 + c[1] = 13 + + // passes vacuously, but does nothing + Assert.assertTrue(delete a[0]) + Assert.assertEquals(a, c); + + var b = new java.util.BitSet() + b.set(2) + // fails to delete a method + try { delete b.get; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + // Method is still there and operational + Assert.assertTrue(b.get(2)) + + // passes vacuously for non-existant property + Assert.assertTrue(delete b.foo) + + // statics + var Calendar = java.util.Calendar + try { delete Calendar.UNDECIMBER; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + try { delete Calendar.availableLocales; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + try { delete Calendar.getInstance; Assert.fail(); } catch (e) { Assert.assertTrue(e instanceof TypeError) } + Assert.assertTrue(delete Calendar.BLAH) // no such thing + + print("Strict beans passed.") +})(); diff --git a/test/nashorn/script/basic/JDK-8193371.js.EXPECTED b/test/nashorn/script/basic/JDK-8193371.js.EXPECTED new file mode 100644 index 00000000000..0cca3c6ac30 --- /dev/null +++ b/test/nashorn/script/basic/JDK-8193371.js.EXPECTED @@ -0,0 +1,6 @@ +List passed. +Strict list passed. +Map passed. +Strict map passed. +Beans passed. +Strict beans passed. From 038b5f571c5cd4f2d615ffbfe4973b10966cb729 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Wed, 20 Dec 2017 09:14:06 -0800 Subject: [PATCH 13/25] 8191913: Bump classfile version number to 55 Co-authored-by: Erik Joelsson Reviewed-by: dholmes, darcy --- make/Main.gmk | 7 +-- make/autoconf/buildjdk-spec.gmk.in | 1 + make/autoconf/flags.m4 | 4 +- make/autoconf/generated-configure.sh | 51 +++++++++++-------- make/autoconf/jdk-version.m4 | 7 +++ make/autoconf/platform.m4 | 8 +++ make/autoconf/spec.gmk.in | 9 ++++ make/autoconf/version-numbers | 2 + make/copy/Copy-java.base.gmk | 14 +++++ make/copy/CopyCommon.gmk | 14 ++--- make/gensrc/GensrcX11Wrappers.gmk | 8 +-- make/hotspot/lib/CompileJvm.gmk | 4 +- .../share/classfile/classFileParser.cpp | 12 ++--- .../com/sun/java/util/jar/pack/Constants.java | 6 ++- .../jdk/internal/module/ModuleInfo.java | 2 +- .../org/objectweb/asm/ClassReader.java | 2 +- .../internal/org/objectweb/asm/Opcodes.java | 1 + ...tants.h => classfile_constants.h.template} | 6 +-- src/java.base/share/native/libjava/System.c | 7 +-- .../com/sun/tools/javac/jvm/ClassFile.java | 3 +- .../com/sun/tools/javac/jvm/Target.java | 2 +- .../replacements/classfile/Classfile.java | 2 +- .../sun/tools/java/RuntimeConstants.java | 2 +- .../runtime/classFileParserBug/Class55.jasm | 43 ++++++++++++++++ .../lang/module/ClassFileVersionsTest.java | 8 ++- .../tools/javac/6330997/T6330997.java | 4 +- .../javac/classfiles/ClassVersionChecker.java | 15 +++--- .../tools/javac/versions/Versions.java | 23 +++++---- 28 files changed, 184 insertions(+), 83 deletions(-) rename src/java.base/share/native/include/{classfile_constants.h => classfile_constants.h.template} (99%) create mode 100644 test/hotspot/jtreg/runtime/classFileParserBug/Class55.jasm diff --git a/make/Main.gmk b/make/Main.gmk index 9e4917b4553..0dc06bd98ef 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -637,7 +637,7 @@ else # Declare dependencies between hotspot-* targets $(foreach v, $(JVM_VARIANTS), \ $(eval hotspot-$v: hotspot-$v-gensrc hotspot-$v-libs) \ - $(eval hotspot-$v-libs: hotspot-$v-gensrc) \ + $(eval hotspot-$v-libs: hotspot-$v-gensrc java.base-copy) \ ) hotspot-ide-project: hotspot exploded-image @@ -691,8 +691,9 @@ else jdk.jdwp.agent-libs: jdk.jdwp.agent-gensrc # The swing beans need to have java base properly generated to avoid errors - # in javadoc. - java.desktop-gensrc-src: java.base-gensrc + # in javadoc. The X11 wrappers need the java.base include files to have been + # copied and processed. + java.desktop-gensrc-src: java.base-gensrc java.base-copy # The annotation processing for jdk.internal.vm.ci and jdk.internal.vm.compiler # needs classes from the current JDK. diff --git a/make/autoconf/buildjdk-spec.gmk.in b/make/autoconf/buildjdk-spec.gmk.in index aceaef7c452..b01d00b7c35 100644 --- a/make/autoconf/buildjdk-spec.gmk.in +++ b/make/autoconf/buildjdk-spec.gmk.in @@ -55,6 +55,7 @@ OPENJDK_TARGET_CPU_ARCH := @OPENJDK_BUILD_CPU_ARCH@ OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@ OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@ OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@ +OPENJDK_TARGET_OS_INCLUDE_SUBDIR := @OPENJDK_BUILD_OS_INCLUDE_SUBDIR@ HOTSPOT_TARGET_OS := @HOTSPOT_BUILD_OS@ HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_BUILD_OS_TYPE@ diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4 index b1c2982aa65..85a014bdbd5 100644 --- a/make/autoconf/flags.m4 +++ b/make/autoconf/flags.m4 @@ -1162,9 +1162,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], # Setup some hard coded includes $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ - -I${TOPDIR}/src/java.base/share/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \ + -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base/\$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ -I${TOPDIR}/src/java.base/share/native/libjava \ -I${TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava \ -I${TOPDIR}/src/hotspot/share/include \ diff --git a/make/autoconf/generated-configure.sh b/make/autoconf/generated-configure.sh index e11acdc166a..224b90c8025 100644 --- a/make/autoconf/generated-configure.sh +++ b/make/autoconf/generated-configure.sh @@ -887,6 +887,8 @@ JAVA BOOT_JDK JAVA_CHECK JAVAC_CHECK +VERSION_CLASSFILE_MINOR +VERSION_CLASSFILE_MAJOR VENDOR_VERSION_STRING VERSION_DATE VERSION_IS_GA @@ -968,6 +970,7 @@ JDK_VARIANT USERNAME TOPDIR PATH_SEP +OPENJDK_BUILD_OS_INCLUDE_SUBDIR HOTSPOT_BUILD_CPU_DEFINE HOTSPOT_BUILD_CPU_ARCH HOTSPOT_BUILD_CPU @@ -978,6 +981,7 @@ OPENJDK_BUILD_CPU_OSARCH OPENJDK_BUILD_CPU_ISADIR OPENJDK_BUILD_CPU_LEGACY_LIB OPENJDK_BUILD_CPU_LEGACY +OPENJDK_TARGET_OS_INCLUDE_SUBDIR HOTSPOT_TARGET_CPU_DEFINE HOTSPOT_TARGET_CPU_ARCH HOTSPOT_TARGET_CPU @@ -1093,7 +1097,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -1383,7 +1386,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1636,15 +1638,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1782,7 +1775,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1935,7 +1928,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -5185,7 +5177,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1513206608 +DATE_WHEN_GENERATED=1513362567 ############################################################################### # @@ -16316,6 +16308,14 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + # For historical reasons, the OS include directories have odd names. + OPENJDK_TARGET_OS_INCLUDE_SUBDIR="$OPENJDK_TARGET_OS" + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + OPENJDK_TARGET_OS_INCLUDE_SUBDIR="win32" + elif test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + OPENJDK_TARGET_OS_INCLUDE_SUBDIR="darwin" + fi + # Also store the legacy naming of the cpu. @@ -16467,6 +16467,14 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + # For historical reasons, the OS include directories have odd names. + OPENJDK_BUILD_OS_INCLUDE_SUBDIR="$OPENJDK_TARGET_OS" + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + OPENJDK_BUILD_OS_INCLUDE_SUBDIR="win32" + elif test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + OPENJDK_BUILD_OS_INCLUDE_SUBDIR="darwin" + fi + @@ -25457,6 +25465,10 @@ fi VENDOR_VERSION_STRING="$with_vendor_version_string" fi + # We could define --with flags for these, if really needed + VERSION_CLASSFILE_MAJOR="$DEFAULT_VERSION_CLASSFILE_MAJOR" + VERSION_CLASSFILE_MINOR="$DEFAULT_VERSION_CLASSFILE_MINOR" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for version string" >&5 $as_echo_n "checking for version string... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VERSION_STRING" >&5 @@ -25478,6 +25490,9 @@ $as_echo "$VERSION_STRING" >&6; } + + + ############################################################################### # # Setup BootJDK, used to bootstrap the build. @@ -52888,9 +52903,7 @@ fi # Setup some hard coded includes COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ - -I${TOPDIR}/src/java.base/share/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ + -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base/\$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ -I${TOPDIR}/src/java.base/share/native/libjava \ -I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava \ -I${TOPDIR}/src/hotspot/share/include \ @@ -53771,9 +53784,7 @@ fi # Setup some hard coded includes OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ - -I${TOPDIR}/src/java.base/share/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \ - -I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \ + -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base/\$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ -I${TOPDIR}/src/java.base/share/native/libjava \ -I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava \ -I${TOPDIR}/src/hotspot/share/include \ diff --git a/make/autoconf/jdk-version.m4 b/make/autoconf/jdk-version.m4 index dff742576b1..772dc592d7b 100644 --- a/make/autoconf/jdk-version.m4 +++ b/make/autoconf/jdk-version.m4 @@ -331,6 +331,10 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], VENDOR_VERSION_STRING="$with_vendor_version_string" fi + # We could define --with flags for these, if really needed + VERSION_CLASSFILE_MAJOR="$DEFAULT_VERSION_CLASSFILE_MAJOR" + VERSION_CLASSFILE_MINOR="$DEFAULT_VERSION_CLASSFILE_MINOR" + AC_MSG_CHECKING([for version string]) AC_MSG_RESULT([$VERSION_STRING]) @@ -348,4 +352,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(VERSION_IS_GA) AC_SUBST(VERSION_DATE) AC_SUBST(VENDOR_VERSION_STRING) + AC_SUBST(VERSION_CLASSFILE_MAJOR) + AC_SUBST(VERSION_CLASSFILE_MINOR) + ]) diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 index f62f94daace..654ce9b2b4e 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.m4 @@ -478,6 +478,14 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], fi AC_SUBST(HOTSPOT_$1_CPU_DEFINE) + # For historical reasons, the OS include directories have odd names. + OPENJDK_$1_OS_INCLUDE_SUBDIR="$OPENJDK_TARGET_OS" + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + OPENJDK_$1_OS_INCLUDE_SUBDIR="win32" + elif test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + OPENJDK_$1_OS_INCLUDE_SUBDIR="darwin" + fi + AC_SUBST(OPENJDK_$1_OS_INCLUDE_SUBDIR) ]) AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 23fcefca74e..383a0f83f33 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -78,6 +78,7 @@ OPENJDK_TARGET_CPU_ISADIR:=@OPENJDK_TARGET_CPU_ISADIR@ OPENJDK_TARGET_CPU_LEGACY:=@OPENJDK_TARGET_CPU_LEGACY@ OPENJDK_TARGET_CPU_LEGACY_LIB:=@OPENJDK_TARGET_CPU_LEGACY_LIB@ OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@ +OPENJDK_TARGET_OS_INCLUDE_SUBIDR:=@OPENJDK_TARGET_OS_INCLUDE_SUBDIR@ HOTSPOT_TARGET_OS := @HOTSPOT_TARGET_OS@ HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_TARGET_OS_TYPE@ @@ -100,6 +101,8 @@ OPENJDK_BUILD_CPU_ARCH:=@OPENJDK_BUILD_CPU_ARCH@ OPENJDK_BUILD_CPU_BITS:=@OPENJDK_BUILD_CPU_BITS@ OPENJDK_BUILD_CPU_ENDIAN:=@OPENJDK_BUILD_CPU_ENDIAN@ +OPENJDK_BUILD_OS_INCLUDE_SUBIDR:=@OPENJDK_TARGET_OS_INCLUDE_SUBDIR@ + # Target platform value in ModuleTarget class file attribute. OPENJDK_MODULE_TARGET_PLATFORM:=@OPENJDK_MODULE_TARGET_PLATFORM@ @@ -175,6 +178,10 @@ VERSION_DATE := @VERSION_DATE@ # Vendor version string VENDOR_VERSION_STRING := @VENDOR_VERSION_STRING@ +# Class-file version +VERSION_CLASSFILE_MAJOR := @VERSION_CLASSFILE_MAJOR@ +VERSION_CLASSFILE_MINOR := @VERSION_CLASSFILE_MINOR@ + # Convenience CFLAGS settings for passing version information into native programs. VERSION_CFLAGS := \ -DVERSION_FEATURE=$(VERSION_FEATURE) \ @@ -190,6 +197,8 @@ VERSION_CFLAGS := \ -DVERSION_SPECIFICATION='"$(VERSION_SPECIFICATION)"' \ -DVERSION_DATE='"$(VERSION_DATE)"' \ -DVENDOR_VERSION_STRING='"$(VENDOR_VERSION_STRING)"' \ + -DVERSION_CLASSFILE_MAJOR=$(VERSION_CLASSFILE_MAJOR) \ + -DVERSION_CLASSFILE_MINOR=$(VERSION_CLASSFILE_MINOR) \ # # Platform naming variables diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index 60d565c1805..fb748470c00 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -30,6 +30,8 @@ DEFAULT_VERSION_INTERIM=0 DEFAULT_VERSION_UPDATE=0 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_DATE=2018-03-20 +DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" +DEFAULT_VERSION_CLASSFILE_MINOR=0 LAUNCHER_NAME=openjdk PRODUCT_NAME=OpenJDK diff --git a/make/copy/Copy-java.base.gmk b/make/copy/Copy-java.base.gmk index 74759879179..096f6c0e903 100644 --- a/make/copy/Copy-java.base.gmk +++ b/make/copy/Copy-java.base.gmk @@ -24,6 +24,7 @@ # include CopyCommon.gmk +include TextFileProcessing.gmk $(eval $(call IncludeCustomExtension, copy/Copy-java.base.gmk)) @@ -244,3 +245,16 @@ ifeq ($(ENABLE_LIBFFI_BUNDLING), true) endif ################################################################################ +# Generate classfile_constants.h + +$(eval $(call SetupTextFileProcessing, CREATE_CLASSFILE_CONSTANTS_H, \ + SOURCE_FILES := $(TOPDIR)/src/java.base/share/native/include/classfile_constants.h.template, \ + OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/modules_include/java.base/classfile_constants.h, \ + REPLACEMENTS := \ + @@VERSION_CLASSFILE_MAJOR@@ => $(VERSION_CLASSFILE_MAJOR) ; \ + @@VERSION_CLASSFILE_MINOR@@ => $(VERSION_CLASSFILE_MINOR) ; , \ +)) + +TARGETS += $(CREATE_CLASSFILE_CONSTANTS_H) + +################################################################################ diff --git a/make/copy/CopyCommon.gmk b/make/copy/CopyCommon.gmk index 2956e9ddf92..6d4cdbaf747 100644 --- a/make/copy/CopyCommon.gmk +++ b/make/copy/CopyCommon.gmk @@ -39,20 +39,12 @@ ifneq ($(wildcard $(INCLUDE_SOURCE_DIR)/*), ) $(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE, \ SRC := $(INCLUDE_SOURCE_DIR), \ DEST := $(INCLUDE_TARGET_DIR), \ - FILES := $(shell $(FIND) $(INCLUDE_SOURCE_DIR) -type f), \ + FILES := $(filter %.h, $(call CacheFind, $(INCLUDE_SOURCE_DIR))), \ )) TARGETS += $(COPY_EXPORTED_INCLUDE) endif -# For historical reasons, the OS include directories have odd names. -INCLUDE_TARGET_OS_SUBDIR := $(OPENJDK_TARGET_OS) -ifeq ($(OPENJDK_TARGET_OS), windows) - INCLUDE_TARGET_OS_SUBDIR := win32 -else ifeq ($(OPENJDK_TARGET_OS), macosx) - INCLUDE_TARGET_OS_SUBDIR := darwin -endif - # Use the most specific of OS and OS_TYPE. INCLUDE_SOURCE_OS_DIR := $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS)/native/include ifeq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), ) @@ -62,8 +54,8 @@ endif ifneq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), ) $(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE_OS, \ SRC := $(INCLUDE_SOURCE_OS_DIR), \ - DEST := $(INCLUDE_TARGET_DIR)/$(INCLUDE_TARGET_OS_SUBDIR), \ - FILES := $(shell $(FIND) $(INCLUDE_SOURCE_OS_DIR) -type f), \ + DEST := $(INCLUDE_TARGET_DIR)/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR), \ + FILES := $(filter %.h, $(call CacheFind, $(INCLUDE_SOURCE_OS_DIR))), \ )) TARGETS += $(COPY_EXPORTED_INCLUDE_OS) diff --git a/make/gensrc/GensrcX11Wrappers.gmk b/make/gensrc/GensrcX11Wrappers.gmk index e506c5c01ff..ca95d0edae9 100644 --- a/make/gensrc/GensrcX11Wrappers.gmk +++ b/make/gensrc/GensrcX11Wrappers.gmk @@ -92,10 +92,10 @@ ifneq ($(COMPILE_TYPE), cross) endif SIZER_CFLAGS := \ - -I${TOPDIR}/src/hotspot/share/include \ - -I${TOPDIR}/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \ - -I$(TOPDIR)/src/java.base/share/native/include \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \ + -I$(TOPDIR)/src/hotspot/share/include \ + -I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ -I$(TOPDIR)/src/java.base/share/native/libjava \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 77ee5d99df1..7be0c043f4a 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -59,8 +59,8 @@ JVM_CFLAGS_INCLUDES += \ -I$(TOPDIR)/src/hotspot/share/precompiled \ -I$(TOPDIR)/src/hotspot/share/include \ -I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \ - -I$(TOPDIR)/src/java.base/share/native/include \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ -I$(TOPDIR)/src/java.base/share/native/libjimage \ # diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 6326ca1e76a..e39d0ee7d66 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -86,8 +86,6 @@ #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE #define JAVA_MIN_SUPPORTED_VERSION 45 -#define JAVA_MAX_SUPPORTED_VERSION 54 -#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 // Used for two backward compatibility reasons: // - to check for new additions to the class file format in JDK1.5 @@ -110,6 +108,8 @@ #define JAVA_10_VERSION 54 +#define JAVA_11_VERSION 55 + void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION, "Unexpected bad constant pool entry"); @@ -4642,11 +4642,11 @@ static bool has_illegal_visibility(jint flags) { } static bool is_supported_version(u2 major, u2 minor){ - const u2 max_version = JAVA_MAX_SUPPORTED_VERSION; + const u2 max_version = JVM_CLASSFILE_MAJOR_VERSION; return (major >= JAVA_MIN_SUPPORTED_VERSION) && (major <= max_version) && ((major != max_version) || - (minor <= JAVA_MAX_SUPPORTED_MINOR_VERSION)); + (minor <= JVM_CLASSFILE_MINOR_VERSION)); } void ClassFileParser::verify_legal_field_modifiers(jint flags, @@ -5808,8 +5808,8 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, _class_name->as_C_string(), _major_version, _minor_version, - JAVA_MAX_SUPPORTED_VERSION, - JAVA_MAX_SUPPORTED_MINOR_VERSION); + JVM_CLASSFILE_MAJOR_VERSION, + JVM_CLASSFILE_MINOR_VERSION); return; } diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java index 5eb79adb6ae..6d2922fb337 100644 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java +++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java @@ -48,6 +48,7 @@ class Constants { 1.8 to 1.8.X 52,0 1.9 to 1.9.X 53,0 1.10 to 1.10.X 54,0 + 1.11 to 1.11.X 55,0 */ public static final Package.Version JAVA_MIN_CLASS_VERSION = @@ -71,6 +72,9 @@ class Constants { public static final Package.Version JAVA10_MAX_CLASS_VERSION = Package.Version.of(54, 00); + public static final Package.Version JAVA11_MAX_CLASS_VERSION = + Package.Version.of(55, 00); + public static final int JAVA_PACKAGE_MAGIC = 0xCAFED00D; public static final Package.Version JAVA5_PACKAGE_VERSION = @@ -87,7 +91,7 @@ class Constants { // upper limit, should point to the latest class version public static final Package.Version JAVA_MAX_CLASS_VERSION = - JAVA10_MAX_CLASS_VERSION; + JAVA11_MAX_CLASS_VERSION; // upper limit should point to the latest package version, for version info!. public static final Package.Version MAX_PACKAGE_VERSION = diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java index 942af76b69d..230695206f0 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java @@ -64,7 +64,7 @@ import static jdk.internal.module.ClassFileConstants.*; public final class ModuleInfo { private final int JAVA_MIN_SUPPORTED_VERSION = 53; - private final int JAVA_MAX_SUPPORTED_VERSION = 54; + private final int JAVA_MAX_SUPPORTED_VERSION = 55; private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index 47e1f6d4b15..22b475f9db9 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -185,7 +185,7 @@ public class ClassReader { public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - if (readShort(off + 6) > Opcodes.V10) { + if (readShort(off + 6) > Opcodes.V11) { throw new IllegalArgumentException(); } // parses the constant pool diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index 7ce9d9210c8..8b3ab18626c 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -90,6 +90,7 @@ public interface Opcodes { int V1_8 = 0 << 16 | 52; int V9 = 0 << 16 | 53; int V10 = 0 << 16 | 54; + int V11 = 0 << 16 | 55; // access flags diff --git a/src/java.base/share/native/include/classfile_constants.h b/src/java.base/share/native/include/classfile_constants.h.template similarity index 99% rename from src/java.base/share/native/include/classfile_constants.h rename to src/java.base/share/native/include/classfile_constants.h.template index 3b63f31c6e8..1046b54b37a 100644 --- a/src/java.base/share/native/include/classfile_constants.h +++ b/src/java.base/share/native/include/classfile_constants.h.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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 @@ -31,8 +31,8 @@ extern "C" { #endif /* Classfile version number for this information */ -#define JVM_CLASSFILE_MAJOR_VERSION 54 -#define JVM_CLASSFILE_MINOR_VERSION 0 +#define JVM_CLASSFILE_MAJOR_VERSION @@VERSION_CLASSFILE_MAJOR@@ +#define JVM_CLASSFILE_MINOR_VERSION @@VERSION_CLASSFILE_MINOR@@ /* Flags */ diff --git a/src/java.base/share/native/libjava/System.c b/src/java.base/share/native/libjava/System.c index 07e638862db..ea432ff6f8e 100644 --- a/src/java.base/share/native/libjava/System.c +++ b/src/java.base/share/native/libjava/System.c @@ -114,9 +114,6 @@ Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x) #define VENDOR_URL_BUG "http://bugreport.java.com/bugreport/" #endif -#define JAVA_MAX_SUPPORTED_VERSION 54 -#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 - #ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed" #else @@ -219,8 +216,8 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) PUTPROP(props, "java.vendor.url", VENDOR_URL); PUTPROP(props, "java.vendor.url.bug", VENDOR_URL_BUG); - jio_snprintf(buf, sizeof(buf), "%d.%d", JAVA_MAX_SUPPORTED_VERSION, - JAVA_MAX_SUPPORTED_MINOR_VERSION); + jio_snprintf(buf, sizeof(buf), "%d.%d", JVM_CLASSFILE_MAJOR_VERSION, + JVM_CLASSFILE_MINOR_VERSION); PUTPROP(props, "java.class.version", buf); if (sprops->awt_toolkit) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java index 6e80995e509..bdb8a8bafa3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java @@ -111,7 +111,8 @@ public class ClassFile { V51(51, 0), // JDK 1.7 V52(52, 0), // JDK 1.8: lambda, type annos, param names V53(53, 0), // JDK 1.9: modules, indy string concat - V54(54, 0); // JDK 10 + V54(54, 0), // JDK 10 + V55(55, 0); // JDK 11: constant dynamic Version(int major, int minor) { this.major = major; this.minor = minor; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index 418d0746088..2c7654df778 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -67,7 +67,7 @@ public enum Target { JDK1_10("1.10", 54, 0), /** JDK 11. */ - JDK1_11("11", 54, 0); // Initially an alias for JDK_10 + JDK1_11("11", 55, 0); private static final Context.Key targetKey = new Context.Key<>(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java index c983a1b466c..48cacb64383 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java @@ -47,7 +47,7 @@ public class Classfile { private final List codeAttributes; private static final int MAJOR_VERSION_JAVA_MIN = 51; - private static final int MAJOR_VERSION_JAVA_MAX = 54; + private static final int MAJOR_VERSION_JAVA_MAX = 55; private static final int MAGIC = 0xCAFEBABE; /** diff --git a/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java b/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java index 85b903d670a..8216220d5d8 100644 --- a/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java +++ b/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java @@ -67,7 +67,7 @@ public interface RuntimeConstants { /* Class File Constants */ int JAVA_MAGIC = 0xcafebabe; int JAVA_MIN_SUPPORTED_VERSION = 45; - int JAVA_MAX_SUPPORTED_VERSION = 54; + int JAVA_MAX_SUPPORTED_VERSION = 55; int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0; /* Generate class file version for 1.1 by default */ diff --git a/test/hotspot/jtreg/runtime/classFileParserBug/Class55.jasm b/test/hotspot/jtreg/runtime/classFileParserBug/Class55.jasm new file mode 100644 index 00000000000..42af9b3206c --- /dev/null +++ b/test/hotspot/jtreg/runtime/classFileParserBug/Class55.jasm @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, 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 8173382 + * @summary Check that the JVM accepts class files with version 55 + * @run main Class55 + */ + +super public class Class55 version 55:0 { + + public Method "":"()V" stack 1 locals 1 { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + + public static Method main:"([Ljava/lang/String;)V" stack 0 locals 1 { + return; + } + +} // end Class Class55 diff --git a/test/jdk/java/lang/module/ClassFileVersionsTest.java b/test/jdk/java/lang/module/ClassFileVersionsTest.java index c7808adb223..e5a74e30a38 100644 --- a/test/jdk/java/lang/module/ClassFileVersionsTest.java +++ b/test/jdk/java/lang/module/ClassFileVersionsTest.java @@ -54,6 +54,8 @@ public class ClassFileVersionsTest { { 53, 0, Set.of(STATIC, TRANSITIVE) }, { 54, 0, Set.of() }, // JDK 10 + + { 55, 0, Set.of()}, // JDK 11 }; } @@ -69,7 +71,11 @@ public class ClassFileVersionsTest { { 54, 0, Set.of(TRANSITIVE) }, { 54, 0, Set.of(STATIC, TRANSITIVE) }, - { 55, 0, Set.of()}, // JDK 11 + { 55, 0, Set.of(STATIC) }, // JDK 11 + { 55, 0, Set.of(TRANSITIVE) }, + { 55, 0, Set.of(STATIC, TRANSITIVE) }, + + { 56, 0, Set.of()}, // JDK 12 }; } diff --git a/test/langtools/tools/javac/6330997/T6330997.java b/test/langtools/tools/javac/6330997/T6330997.java index 3e4d8e535ed..fdaf5db698e 100644 --- a/test/langtools/tools/javac/6330997/T6330997.java +++ b/test/langtools/tools/javac/6330997/T6330997.java @@ -32,8 +32,8 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.util * @clean T1 T2 - * @compile -source 10 -target 10 T1.java - * @compile -source 10 -target 10 T2.java + * @compile -source 10 -target 11 T1.java + * @compile -source 10 -target 11 T2.java * @run main/othervm T6330997 */ diff --git a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java index 4a6cf188c89..f9f1e18fdd9 100644 --- a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java +++ b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7157626 8001112 8188870 + * @bug 7157626 8001112 8188870 8173382 * @summary Test major version for all legal combinations for -source and -target * @author sgoel * @@ -38,7 +38,7 @@ import java.util.regex.*; public class ClassVersionChecker { int errors; - String[] jdk = {"", "1.6", "1.7", "1.8", "1.9", "1.10"}; + String[] jdk = {"", "1.6", "1.7", "1.8", "1.9", "1.10", "11"}; File javaFile = null; public static void main(String[] args) throws Throwable { @@ -58,11 +58,12 @@ public class ClassVersionChecker { * -1 => invalid combinations */ int[][] ver = - {{54, -1, -1, -1, -1, -1}, - {54, 50, 51, 52, 53, 54}, - {54, -1, 51, 52, 53, 54}, - {54, -1, -1, 52, 53, 54}, - {54, -1, -1, -1, 53, 54}}; + {{55, -1, -1, -1, -1, -1, -1}, + {55, 50, 51, 52, 53, 54, 55}, + {55, -1, 51, 52, 53, 54, 55}, + {55, -1, -1, 52, 53, 54, 55}, + {55, -1, -1, -1, 53, 54, 55}, + {55, -1, -1, -1, -1, 54, 55}}; // Loop to run all possible combinations of source/target values for (int i = 0; i< ver.length; i++) { diff --git a/test/langtools/tools/javac/versions/Versions.java b/test/langtools/tools/javac/versions/Versions.java index 8e3fc8b026b..ea5e9a9959d 100644 --- a/test/langtools/tools/javac/versions/Versions.java +++ b/test/langtools/tools/javac/versions/Versions.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112 8028545 8000961 8030610 8028546 8188870 8173382 + * @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112 8028545 8000961 8030610 8028546 8188870 8173382 8173382 * @summary Check interpretation of -target and -source options * @modules java.compiler * jdk.compiler @@ -64,13 +64,13 @@ public class Versions { String TC = ""; System.out.println("Version.java: Starting"); - check("54.0"); - check("54.0", "-source 1.6"); - check("54.0", "-source 1.7"); - check("54.0", "-source 1.8"); - check("54.0", "-source 1.9"); - check("54.0", "-source 1.10"); - check("54.0", "-source 11"); + check("55.0"); + check("55.0", "-source 1.6"); + check("55.0", "-source 1.7"); + check("55.0", "-source 1.8"); + check("55.0", "-source 1.9"); + check("55.0", "-source 1.10"); + check("55.0", "-source 11"); check_source_target(true, "50.0", "6", "6"); check_source_target(true, "51.0", "6", "7"); @@ -87,7 +87,12 @@ public class Versions { check_source_target(true, "54.0", "8", "10"); check_source_target(true, "54.0", "9", "10"); check_source_target(true, "54.0", "10", "10"); - check_source_target(false, "54.0", "11", "11"); + check_source_target(false, "55.0", "6", "11"); + check_source_target(false, "55.0", "7", "11"); + check_source_target(false, "55.0", "8", "11"); + check_source_target(false, "55.0", "9", "11"); + check_source_target(false, "55.0", "10", "11"); + check_source_target(false, "55.0", "11", "11"); checksrc16("-source 1.6"); checksrc16("-source 6"); From fb9db6b02de7eabdc13ae9af47dfe58467fc4580 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Wed, 20 Dec 2017 09:14:52 -0800 Subject: [PATCH 14/25] 8193085: Vectorize the nio Buffer equals and compareTo implementations Reviewed-by: alanb --- src/hotspot/share/classfile/vmSymbols.hpp | 4 +- .../share/classes/java/nio/Bits.java | 58 +- .../share/classes/java/nio/Buffer.java | 11 + .../classes/java/nio/BufferMismatch.java | 198 +++++ .../nio/ByteBufferAs-X-Buffer.java.template | 23 +- .../nio/Direct-X-Buffer-bin.java.template | 6 +- .../java/nio/Direct-X-Buffer.java.template | 56 +- .../java/nio/Heap-X-Buffer.java.template | 83 +-- .../classes/java/nio/StringCharBuffer.java | 26 + .../classes/java/nio/X-Buffer.java.template | 39 +- .../share/classes/java/util/Arrays.java | 1 + .../internal}/util/ArraysSupport.java | 126 ++-- .../java/nio/Buffer/EqualsCompareTest.java | 686 ++++++++++++++++++ 13 files changed, 1122 insertions(+), 195 deletions(-) create mode 100644 src/java.base/share/classes/java/nio/BufferMismatch.java rename src/java.base/share/classes/{java => jdk/internal}/util/ArraysSupport.java (83%) create mode 100644 test/jdk/java/nio/Buffer/EqualsCompareTest.java diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 65246e04bae..ddc54315ade 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -996,8 +996,8 @@ do_name( montgomerySquare_name, "implMontgomerySquare") \ do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \ \ - do_class(java_util_ArraysSupport, "java/util/ArraysSupport") \ - do_intrinsic(_vectorizedMismatch, java_util_ArraysSupport, vectorizedMismatch_name, vectorizedMismatch_signature, F_S)\ + do_class(jdk_internal_util_ArraysSupport, "jdk/internal/util/ArraysSupport") \ + do_intrinsic(_vectorizedMismatch, jdk_internal_util_ArraysSupport, vectorizedMismatch_name, vectorizedMismatch_signature, F_S)\ do_name(vectorizedMismatch_name, "vectorizedMismatch") \ do_signature(vectorizedMismatch_signature, "(Ljava/lang/Object;JLjava/lang/Object;JII)I") \ \ diff --git a/src/java.base/share/classes/java/nio/Bits.java b/src/java.base/share/classes/java/nio/Bits.java index dfe6a8f13a7..fff84e9e58d 100644 --- a/src/java.base/share/classes/java/nio/Bits.java +++ b/src/java.base/share/classes/java/nio/Bits.java @@ -63,38 +63,38 @@ class Bits { // package-private // -- Unsafe access -- - private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); static Unsafe unsafe() { - return unsafe; + return UNSAFE; } // -- Processor and memory-system properties -- - private static final ByteOrder byteOrder - = unsafe.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + private static final ByteOrder BYTE_ORDER + = UNSAFE.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; static ByteOrder byteOrder() { - return byteOrder; + return BYTE_ORDER; } - private static int pageSize = -1; + private static int PAGE_SIZE = -1; static int pageSize() { - if (pageSize == -1) - pageSize = unsafe().pageSize(); - return pageSize; + if (PAGE_SIZE == -1) + PAGE_SIZE = unsafe().pageSize(); + return PAGE_SIZE; } static int pageCount(long size) { return (int)(size + (long)pageSize() - 1L) / pageSize(); } - private static boolean unaligned = unsafe.unalignedAccess(); + private static boolean UNALIGNED = UNSAFE.unalignedAccess(); static boolean unaligned() { - return unaligned; + return UNALIGNED; } @@ -103,11 +103,11 @@ class Bits { // package-private // A user-settable upper limit on the maximum amount of allocatable // direct buffer memory. This value may be changed during VM // initialization if it is launched with "-XX:MaxDirectMemorySize=". - private static volatile long maxMemory = VM.maxDirectMemory(); - private static final AtomicLong reservedMemory = new AtomicLong(); - private static final AtomicLong totalCapacity = new AtomicLong(); - private static final AtomicLong count = new AtomicLong(); - private static volatile boolean memoryLimitSet; + private static volatile long MAX_MEMORY = VM.maxDirectMemory(); + private static final AtomicLong RESERVED_MEMORY = new AtomicLong(); + private static final AtomicLong TOTAL_CAPACITY = new AtomicLong(); + private static final AtomicLong COUNT = new AtomicLong(); + private static volatile boolean MEMORY_LIMIT_SET; // max. number of sleeps during try-reserving with exponentially // increasing delay before throwing OutOfMemoryError: @@ -120,9 +120,9 @@ class Bits { // package-private // which a process may access. All sizes are specified in bytes. static void reserveMemory(long size, int cap) { - if (!memoryLimitSet && VM.initLevel() >= 1) { - maxMemory = VM.maxDirectMemory(); - memoryLimitSet = true; + if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) { + MAX_MEMORY = VM.maxDirectMemory(); + MEMORY_LIMIT_SET = true; } // optimist! @@ -200,10 +200,10 @@ class Bits { // package-private // actual memory usage, which will differ when buffers are page // aligned. long totalCap; - while (cap <= maxMemory - (totalCap = totalCapacity.get())) { - if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) { - reservedMemory.addAndGet(size); - count.incrementAndGet(); + while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) { + if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) { + RESERVED_MEMORY.addAndGet(size); + COUNT.incrementAndGet(); return true; } } @@ -213,9 +213,9 @@ class Bits { // package-private static void unreserveMemory(long size, int cap) { - long cnt = count.decrementAndGet(); - long reservedMem = reservedMemory.addAndGet(-size); - long totalCap = totalCapacity.addAndGet(-cap); + long cnt = COUNT.decrementAndGet(); + long reservedMem = RESERVED_MEMORY.addAndGet(-size); + long totalCap = TOTAL_CAPACITY.addAndGet(-cap); assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0; } @@ -234,15 +234,15 @@ class Bits { // package-private } @Override public long getCount() { - return Bits.count.get(); + return Bits.COUNT.get(); } @Override public long getTotalCapacity() { - return Bits.totalCapacity.get(); + return Bits.TOTAL_CAPACITY.get(); } @Override public long getMemoryUsed() { - return Bits.reservedMemory.get(); + return Bits.RESERVED_MEMORY.get(); } }; } diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index 1f6bef17960..1217ca78a74 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.java @@ -26,6 +26,7 @@ package java.nio; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.misc.Unsafe; import java.util.Spliterator; @@ -181,6 +182,8 @@ import java.util.Spliterator; */ public abstract class Buffer { + // Cached unsafe-access object + static final Unsafe UNSAFE = Bits.unsafe(); /** * The characteristics of Spliterators that traverse and split elements @@ -616,6 +619,14 @@ public abstract class Buffer { // -- Package-private methods for bounds checking, etc. -- + /** + * + * @return the base reference, paired with the address + * field, which in combination can be used for unsafe access into a heap + * buffer or direct byte buffer (and views of). + */ + abstract Object base(); + /** * Checks the current position against the limit, throwing a {@link * BufferUnderflowException} if it is not smaller than the limit, and then diff --git a/src/java.base/share/classes/java/nio/BufferMismatch.java b/src/java.base/share/classes/java/nio/BufferMismatch.java new file mode 100644 index 00000000000..c1260f62a19 --- /dev/null +++ b/src/java.base/share/classes/java/nio/BufferMismatch.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017, 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 java.nio; + +import jdk.internal.util.ArraysSupport; + +/** + * Mismatch methods for buffers + */ +final class BufferMismatch { + + static int mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length) { + int i = 0; + if (length > 7) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + aOff, + b.base(), b.address + bOff, + length, + ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE); + if (i >= 0) return i; + i = length - ~i; + } + for (; i < length; i++) { + if (a.get(aOff + i) != b.get(bOff + i)) + return i; + } + return -1; + } + + static int mismatch(CharBuffer a, int aOff, CharBuffer b, int bOff, int length) { + int i = 0; + // Ensure only heap or off-heap buffer instances use the + // vectorized mismatch. If either buffer is a StringCharBuffer + // (order is null) then the slow path is taken + if (length > 3 && a.charRegionOrder() == b.charRegionOrder() + && a.charRegionOrder() != null && b.charRegionOrder() != null) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE); + if (i >= 0) return i; + i = length - ~i; + } + for (; i < length; i++) { + if (a.get(aOff + i) != b.get(bOff + i)) + return i; + } + return -1; + } + + static int mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length) { + int i = 0; + if (length > 3 && a.order() == b.order()) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE); + if (i >= 0) return i; + i = length - ~i; + } + for (; i < length; i++) { + if (a.get(aOff + i) != b.get(bOff + i)) + return i; + } + return -1; + } + + static int mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length) { + int i = 0; + if (length > 1 && a.order() == b.order()) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE); + if (i >= 0) return i; + i = length - ~i; + } + for (; i < length; i++) { + if (a.get(aOff + i) != b.get(bOff + i)) + return i; + } + return -1; + } + + static int mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length) { + int i = 0; + if (length > 1 && a.order() == b.order()) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE); + // Mismatched + if (i >= 0) { + // Check if mismatch is not associated with two NaN values; and + // is not associated with +0 and -0 + float av = a.get(aOff + i); + float bv = b.get(bOff + i); + if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv))) + return i; + + // Fall back to slow mechanism + // ISSUE: Consider looping over vectorizedMismatch adjusting ranges + // However, requires that returned value be relative to input ranges + i++; + } + // Matched + else { + i = length - ~i; + } + } + for (; i < length; i++) { + float av = a.get(aOff + i); + float bv = b.get(bOff + i); + if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv))) + return i; + } + return -1; + } + + static int mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length) { + int i = 0; + if (length > 0 && a.order() == b.order()) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE); + return i >= 0 ? i : -1; + } + for (; i < length; i++) { + if (a.get(aOff + i) != b.get(bOff + i)) + return i; + } + return -1; + } + + static int mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length) { + int i = 0; + if (length > 0 && a.order() == b.order()) { + i = ArraysSupport.vectorizedMismatch( + a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE), + b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE), + length, + ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE); + // Mismatched + if (i >= 0) { + // Check if mismatch is not associated with two NaN values; and + // is not associated with +0 and -0 + double av = a.get(aOff + i); + double bv = b.get(bOff + i); + if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv))) + return i; + + // Fall back to slow mechanism + // ISSUE: Consider looping over vectorizedMismatch adjusting ranges + // However, requires that returned value be relative to input ranges + i++; + } + // Matched + else { + return -1; + } + } + for (; i < length; i++) { + double av = a.get(aOff + i); + double bv = b.get(bOff + i); + if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv))) + return i; + } + return -1; + } +} diff --git a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template index 3ceb4122b62..b390448b110 100644 --- a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template @@ -36,9 +36,6 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private #if[rw] - // Cached unsafe-access object - private static final Unsafe unsafe = Bits.unsafe(); - protected final ByteBuffer bb; #end[rw] @@ -74,6 +71,11 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private #end[rw] } + @Override + Object base() { + return bb.hb; + } + public $Type$Buffer slice() { int pos = this.position(); int lim = this.limit(); @@ -117,20 +119,20 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private } public $type$ get() { - $memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()), + $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()), {#if[boB]?true:false}); return $fromBits$(x); } public $type$ get(int i) { - $memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), + $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), {#if[boB]?true:false}); return $fromBits$(x); } #if[streamableType] $type$ getUnchecked(int i) { - $memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(i), + $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(i), {#if[boB]?true:false}); return $fromBits$(x); } @@ -141,7 +143,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private public $Type$Buffer put($type$ x) { #if[rw] $memtype$ y = $toBits$(x); - unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y, + UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y, {#if[boB]?true:false}); return this; #else[rw] @@ -152,7 +154,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private public $Type$Buffer put(int i, $type$ x) { #if[rw] $memtype$ y = $toBits$(x); - unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y, + UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y, {#if[boB]?true:false}); return this; #else[rw] @@ -241,4 +243,9 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private #end[boL] } +#if[char] + ByteOrder charRegionOrder() { + return order(); + } +#end[char] } diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template index 6179776100d..cacadb101df 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template @@ -32,7 +32,7 @@ class XXX { #if[rw] private $type$ get$Type$(long a) { - $memtype$ x = unsafe.get$Memtype$Unaligned(null, a, bigEndian); + $memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian); return $fromBits$(x); } @@ -49,7 +49,7 @@ class XXX { private ByteBuffer put$Type$(long a, $type$ x) { #if[rw] $memtype$ y = $toBits$(x); - unsafe.put$Memtype$Unaligned(null, a, y, bigEndian); + UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -81,7 +81,7 @@ class XXX { int rem = (off <= lim ? lim - off : 0); int size = rem >> $LG_BYTES_PER_VALUE$; - if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) { + if (!UNALIGNED && ((address + off) % $BYTES_PER_VALUE$ != 0)) { return (bigEndian ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this, -1, diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 68ec8340e0d..5fa9be47b20 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -28,7 +28,6 @@ package java.nio; import java.io.FileDescriptor; -import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.ref.Cleaner; import sun.nio.ch.DirectBuffer; @@ -45,14 +44,11 @@ class Direct$Type$Buffer$RW$$BO$ #if[rw] - // Cached unsafe-access object - protected static final Unsafe unsafe = Bits.unsafe(); - // Cached array base offset - private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class); + private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class); // Cached unaligned-access capability - protected static final boolean unaligned = Bits.unaligned(); + protected static final boolean UNALIGNED = Bits.unaligned(); // Base address, used in all indexing calculations // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress @@ -73,8 +69,6 @@ class Direct$Type$Buffer$RW$$BO$ implements Runnable { - private static Unsafe unsafe = Unsafe.getUnsafe(); - private long address; private long size; private int capacity; @@ -91,7 +85,7 @@ class Direct$Type$Buffer$RW$$BO$ // Paranoia return; } - unsafe.freeMemory(address); + UNSAFE.freeMemory(address); address = 0; Bits.unreserveMemory(size, capacity); } @@ -124,12 +118,12 @@ class Direct$Type$Buffer$RW$$BO$ long base = 0; try { - base = unsafe.allocateMemory(size); + base = UNSAFE.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.unreserveMemory(size, cap); throw x; } - unsafe.setMemory(base, size, (byte) 0); + UNSAFE.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); @@ -206,6 +200,11 @@ class Direct$Type$Buffer$RW$$BO$ #end[rw] } + @Override + Object base() { + return null; + } + public $Type$Buffer slice() { int pos = this.position(); int lim = this.limit(); @@ -258,16 +257,16 @@ class Direct$Type$Buffer$RW$$BO$ } public $type$ get() { - return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex())))); + return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex())))); } public $type$ get(int i) { - return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i))))); + return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i))))); } #if[streamableType] $type$ getUnchecked(int i) { - return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i)))); + return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i)))); } #end[streamableType] @@ -282,10 +281,10 @@ class Direct$Type$Buffer$RW$$BO$ if (length > rem) throw new BufferUnderflowException(); - long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); + long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); #if[!byte] if (order() != ByteOrder.nativeOrder()) - unsafe.copySwapMemory(null, + UNSAFE.copySwapMemory(null, ix(pos), dst, dstOffset, @@ -293,7 +292,7 @@ class Direct$Type$Buffer$RW$$BO$ (long)1 << $LG_BYTES_PER_VALUE$); else #end[!byte] - unsafe.copyMemory(null, + UNSAFE.copyMemory(null, ix(pos), dst, dstOffset, @@ -312,7 +311,7 @@ class Direct$Type$Buffer$RW$$BO$ public $Type$Buffer put($type$ x) { #if[rw] - unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x))); + UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x))); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -321,7 +320,7 @@ class Direct$Type$Buffer$RW$$BO$ public $Type$Buffer put(int i, $type$ x) { #if[rw] - unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x))); + UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x))); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -347,7 +346,7 @@ class Direct$Type$Buffer$RW$$BO$ if (srem > rem) throw new BufferOverflowException(); - unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$); + UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$); sb.position(spos + srem); position(pos + srem); } else if (src.hb != null) { @@ -380,10 +379,10 @@ class Direct$Type$Buffer$RW$$BO$ if (length > rem) throw new BufferOverflowException(); - long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); + long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$); #if[!byte] if (order() != ByteOrder.nativeOrder()) - unsafe.copySwapMemory(src, + UNSAFE.copySwapMemory(src, srcOffset, null, ix(pos), @@ -391,7 +390,7 @@ class Direct$Type$Buffer$RW$$BO$ (long)1 << $LG_BYTES_PER_VALUE$); else #end[!byte] - unsafe.copyMemory(src, + UNSAFE.copyMemory(src, srcOffset, null, ix(pos), @@ -413,7 +412,7 @@ class Direct$Type$Buffer$RW$$BO$ assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$); + UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$); position(rem); limit(capacity()); discardMark(); @@ -490,17 +489,22 @@ class Direct$Type$Buffer$RW$$BO$ #end[!byte] +#if[char] + ByteOrder charRegionOrder() { + return order(); + } +#end[char] #if[byte] byte _get(int i) { // package-private - return unsafe.getByte(address + i); + return UNSAFE.getByte(address + i); } void _put(int i, byte b) { // package-private #if[rw] - unsafe.putByte(address + i, b); + UNSAFE.putByte(address + i, b); #else[rw] throw new ReadOnlyBufferException(); #end[rw] diff --git a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template index 69e65a099c7..7f2a2597ba3 100644 --- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template @@ -27,8 +27,6 @@ package java.nio; -import jdk.internal.misc.Unsafe; - /** #if[rw] * A read/write Heap$Type$Buffer. @@ -43,6 +41,11 @@ import jdk.internal.misc.Unsafe; class Heap$Type$Buffer$RW$ extends {#if[ro]?Heap}$Type$Buffer { + // Cached array base offset + private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class); + + // Cached array base offset + private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class); // For speed these fields are actually declared in X-Buffer; // these declarations are here as documentation @@ -53,16 +56,6 @@ class Heap$Type$Buffer$RW$ #end[rw] */ -#if[byte] - - // Cached unsafe-access object - private static final Unsafe unsafe = Bits.unsafe(); - - // Cached array base offset - private static final long arrayBaseOffset = unsafe.arrayBaseOffset($type$[].class); - -#end[byte] - Heap$Type$Buffer$RW$(int cap, int lim) { // package-private #if[rw] super(-1, 0, lim, cap, new $type$[cap], 0); @@ -70,13 +63,11 @@ class Heap$Type$Buffer$RW$ hb = new $type$[cap]; offset = 0; */ + this.address = ARRAY_BASE_OFFSET; #else[rw] super(cap, lim); this.isReadOnly = true; #end[rw] -#if[byte] - this.address = arrayBaseOffset; -#end[byte] } Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private @@ -86,13 +77,11 @@ class Heap$Type$Buffer$RW$ hb = buf; offset = 0; */ + this.address = ARRAY_BASE_OFFSET; #else[rw] super(buf, off, len); this.isReadOnly = true; #end[rw] -#if[byte] - this.address = arrayBaseOffset; -#end[byte] } protected Heap$Type$Buffer$RW$($type$[] buf, @@ -105,13 +94,11 @@ class Heap$Type$Buffer$RW$ hb = buf; offset = off; */ + this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE; #else[rw] super(buf, mark, pos, lim, cap, off); this.isReadOnly = true; #end[rw] -#if[byte] - this.address = arrayBaseOffset + off; -#end[byte] } public $Type$Buffer slice() { @@ -296,18 +283,18 @@ class Heap$Type$Buffer$RW$ #if[rw] public char getChar() { - return unsafe.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian); + return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian); } public char getChar(int i) { - return unsafe.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); + return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); } #end[rw] public $Type$Buffer putChar(char x) { #if[rw] - unsafe.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian); + UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -316,7 +303,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putChar(int i, char x) { #if[rw] - unsafe.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian); + UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -347,18 +334,18 @@ class Heap$Type$Buffer$RW$ #if[rw] public short getShort() { - return unsafe.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian); + return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian); } public short getShort(int i) { - return unsafe.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); + return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian); } #end[rw] public $Type$Buffer putShort(short x) { #if[rw] - unsafe.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian); + UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -367,7 +354,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putShort(int i, short x) { #if[rw] - unsafe.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian); + UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -398,18 +385,18 @@ class Heap$Type$Buffer$RW$ #if[rw] public int getInt() { - return unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); + return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); } public int getInt(int i) { - return unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); + return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); } #end[rw] public $Type$Buffer putInt(int x) { #if[rw] - unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian); + UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -418,7 +405,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putInt(int i, int x) { #if[rw] - unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian); + UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -449,18 +436,18 @@ class Heap$Type$Buffer$RW$ #if[rw] public long getLong() { - return unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian); + return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian); } public long getLong(int i) { - return unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); + return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); } #end[rw] public $Type$Buffer putLong(long x) { #if[rw] - unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian); + UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -469,7 +456,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putLong(int i, long x) { #if[rw] - unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian); + UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -500,12 +487,12 @@ class Heap$Type$Buffer$RW$ #if[rw] public float getFloat() { - int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); + int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); return Float.intBitsToFloat(x); } public float getFloat(int i) { - int x = unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); + int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); return Float.intBitsToFloat(x); } @@ -514,7 +501,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putFloat(float x) { #if[rw] int y = Float.floatToRawIntBits(x); - unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian); + UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -524,7 +511,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putFloat(int i, float x) { #if[rw] int y = Float.floatToRawIntBits(x); - unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian); + UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -555,12 +542,12 @@ class Heap$Type$Buffer$RW$ #if[rw] public double getDouble() { - long x = unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian); + long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian); return Double.longBitsToDouble(x); } public double getDouble(int i) { - long x = unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); + long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian); return Double.longBitsToDouble(x); } @@ -569,7 +556,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putDouble(double x) { #if[rw] long y = Double.doubleToRawLongBits(x); - unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian); + UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -579,7 +566,7 @@ class Heap$Type$Buffer$RW$ public $Type$Buffer putDouble(int i, double x) { #if[rw] long y = Double.doubleToRawLongBits(x); - unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian); + UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian); return this; #else[rw] throw new ReadOnlyBufferException(); @@ -643,7 +630,11 @@ class Heap$Type$Buffer$RW$ public ByteOrder order() { return ByteOrder.nativeOrder(); } - #end[!byte] +#if[char] + ByteOrder charRegionOrder() { + return order(); + } +#end[char] } diff --git a/src/java.base/share/classes/java/nio/StringCharBuffer.java b/src/java.base/share/classes/java/nio/StringCharBuffer.java index 71f4b368d29..26b355bc819 100644 --- a/src/java.base/share/classes/java/nio/StringCharBuffer.java +++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java @@ -127,4 +127,30 @@ class StringCharBuffer // package-private return ByteOrder.nativeOrder(); } + ByteOrder charRegionOrder() { + return null; + } + + public boolean equals(Object ob) { + if (this == ob) + return true; + if (!(ob instanceof CharBuffer)) + return false; + CharBuffer that = (CharBuffer)ob; + if (this.remaining() != that.remaining()) + return false; + return BufferMismatch.mismatch(this, this.position(), + that, that.position(), + this.remaining()) < 0; + } + + public int compareTo(CharBuffer that) { + int i = BufferMismatch.mismatch(this, this.position(), + that, that.position(), + Math.min(this.remaining(), that.remaining())); + if (i >= 0) { + return Character.compare(this.get(this.position() + i), that.get(this.position() + i)); + } + return this.remaining() - that.remaining(); + } } diff --git a/src/java.base/share/classes/java/nio/X-Buffer.java.template b/src/java.base/share/classes/java/nio/X-Buffer.java.template index 0a39543a88e..96e05d6a663 100644 --- a/src/java.base/share/classes/java/nio/X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template @@ -36,6 +36,8 @@ import java.util.stream.StreamSupport; import java.util.stream.$Streamtype$Stream; #end[streamableType] +import jdk.internal.util.ArraysSupport; + /** * $A$ $type$ buffer. * @@ -287,6 +289,11 @@ public abstract class $Type$Buffer this(mark, pos, lim, cap, null, 0); } + @Override + Object base() { + return hb; + } + #if[byte] /** @@ -1297,19 +1304,9 @@ public abstract class $Type$Buffer $Type$Buffer that = ($Type$Buffer)ob; if (this.remaining() != that.remaining()) return false; - int p = this.position(); - for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) - if (!equals(this.get(i), that.get(j))) - return false; - return true; - } - - private static boolean equals($type$ x, $type$ y) { -#if[floatingPointType] - return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y)); -#else[floatingPointType] - return x == y; -#end[floatingPointType] + return BufferMismatch.mismatch(this, this.position(), + that, that.position(), + this.remaining()) < 0; } /** @@ -1336,11 +1333,11 @@ public abstract class $Type$Buffer * is less than, equal to, or greater than the given buffer */ public int compareTo($Type$Buffer that) { - int n = this.position() + Math.min(this.remaining(), that.remaining()); - for (int i = this.position(), j = that.position(); i < n; i++, j++) { - int cmp = compare(this.get(i), that.get(j)); - if (cmp != 0) - return cmp; + int i = BufferMismatch.mismatch(this, this.position(), + that, that.position(), + Math.min(this.remaining(), that.remaining())); + if (i >= 0) { + return compare(this.get(this.position() + i), that.get(this.position() + i)); } return this.remaining() - that.remaining(); } @@ -1571,6 +1568,12 @@ public abstract class $Type$Buffer #end[!byte] +#if[char] + // The order or null if the buffer does not cover a memory region, + // such as StringCharBuffer + abstract ByteOrder charRegionOrder(); +#end[char] + #if[byte] boolean bigEndian // package-private diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java index e1571cc613f..74011566f26 100644 --- a/src/java.base/share/classes/java/util/Arrays.java +++ b/src/java.base/share/classes/java/util/Arrays.java @@ -26,6 +26,7 @@ package java.util; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.ArraysSupport; import java.lang.reflect.Array; import java.util.concurrent.ForkJoinPool; diff --git a/src/java.base/share/classes/java/util/ArraysSupport.java b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java similarity index 83% rename from src/java.base/share/classes/java/util/ArraysSupport.java rename to src/java.base/share/classes/jdk/internal/util/ArraysSupport.java index 31612a7d4f8..cc051df7d31 100644 --- a/src/java.base/share/classes/java/util/ArraysSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017 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,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package java.util; +package jdk.internal.util; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.misc.Unsafe; @@ -50,19 +50,19 @@ import jdk.internal.misc.Unsafe; * responsibility of the caller (direct or otherwise) to perform such checks * before calling this method. */ -class ArraysSupport { +public class ArraysSupport { static final Unsafe U = Unsafe.getUnsafe(); private static final boolean BIG_ENDIAN = U.isBigEndian(); - private static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE); - private static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE); - private static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE); - private static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE); - private static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE); - private static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE); - private static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE); - private static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE); + public static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE); + public static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE); + public static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE); + public static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE); + public static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE); + public static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE); + public static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE); + public static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE); private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE); @@ -107,10 +107,10 @@ class ArraysSupport { * the tail of the two arrays. */ @HotSpotIntrinsicCandidate - static int vectorizedMismatch(Object a, long aOffset, - Object b, long bOffset, - int length, - int log2ArrayIndexScale) { + public static int vectorizedMismatch(Object a, long aOffset, + Object b, long bOffset, + int length, + int log2ArrayIndexScale) { // assert a.getClass().isArray(); // assert b.getClass().isArray(); // assert 0 <= length <= sizeOf(a) @@ -161,9 +161,9 @@ class ArraysSupport { // Booleans // Each boolean element takes up one byte - static int mismatch(boolean[] a, - boolean[] b, - int length) { + public static int mismatch(boolean[] a, + boolean[] b, + int length) { int i = 0; if (length > 7) { i = vectorizedMismatch( @@ -181,9 +181,9 @@ class ArraysSupport { return -1; } - static int mismatch(boolean[] a, int aFromIndex, - boolean[] b, int bFromIndex, - int length) { + public static int mismatch(boolean[] a, int aFromIndex, + boolean[] b, int bFromIndex, + int length) { int i = 0; if (length > 7) { int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex; @@ -219,9 +219,9 @@ class ArraysSupport { * no mismatch. The index will be within the range of (inclusive) 0 to * (exclusive) the smaller of the two array lengths. */ - static int mismatch(byte[] a, - byte[] b, - int length) { + public static int mismatch(byte[] a, + byte[] b, + int length) { // ISSUE: defer to index receiving methods if performance is good // assert length <= a.length // assert length <= b.length @@ -264,9 +264,9 @@ class ArraysSupport { * otherwise -1 if no mismatch. The index will be within the range of * (inclusive) 0 to (exclusive) the smaller of the two array bounds. */ - static int mismatch(byte[] a, int aFromIndex, - byte[] b, int bFromIndex, - int length) { + public static int mismatch(byte[] a, int aFromIndex, + byte[] b, int bFromIndex, + int length) { // assert 0 <= aFromIndex < a.length // assert 0 <= aFromIndex + length <= a.length // assert 0 <= bFromIndex < b.length @@ -295,9 +295,9 @@ class ArraysSupport { // Chars - static int mismatch(char[] a, - char[] b, - int length) { + public static int mismatch(char[] a, + char[] b, + int length) { int i = 0; if (length > 3) { i = vectorizedMismatch( @@ -315,9 +315,9 @@ class ArraysSupport { return -1; } - static int mismatch(char[] a, int aFromIndex, - char[] b, int bFromIndex, - int length) { + public static int mismatch(char[] a, int aFromIndex, + char[] b, int bFromIndex, + int length) { int i = 0; if (length > 3) { int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE); @@ -340,9 +340,9 @@ class ArraysSupport { // Shorts - static int mismatch(short[] a, - short[] b, - int length) { + public static int mismatch(short[] a, + short[] b, + int length) { int i = 0; if (length > 3) { i = vectorizedMismatch( @@ -360,9 +360,9 @@ class ArraysSupport { return -1; } - static int mismatch(short[] a, int aFromIndex, - short[] b, int bFromIndex, - int length) { + public static int mismatch(short[] a, int aFromIndex, + short[] b, int bFromIndex, + int length) { int i = 0; if (length > 3) { int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE); @@ -385,9 +385,9 @@ class ArraysSupport { // Ints - static int mismatch(int[] a, - int[] b, - int length) { + public static int mismatch(int[] a, + int[] b, + int length) { int i = 0; if (length > 1) { i = vectorizedMismatch( @@ -405,9 +405,9 @@ class ArraysSupport { return -1; } - static int mismatch(int[] a, int aFromIndex, - int[] b, int bFromIndex, - int length) { + public static int mismatch(int[] a, int aFromIndex, + int[] b, int bFromIndex, + int length) { int i = 0; if (length > 1) { int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE); @@ -430,15 +430,15 @@ class ArraysSupport { // Floats - static int mismatch(float[] a, - float[] b, - int length) { + public static int mismatch(float[] a, + float[] b, + int length) { return mismatch(a, 0, b, 0, length); } - static int mismatch(float[] a, int aFromIndex, - float[] b, int bFromIndex, - int length) { + public static int mismatch(float[] a, int aFromIndex, + float[] b, int bFromIndex, + int length) { int i = 0; if (length > 1) { int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE); @@ -475,9 +475,9 @@ class ArraysSupport { // Long - static int mismatch(long[] a, - long[] b, - int length) { + public static int mismatch(long[] a, + long[] b, + int length) { if (length == 0) { return -1; } @@ -488,9 +488,9 @@ class ArraysSupport { return i >= 0 ? i : -1; } - static int mismatch(long[] a, int aFromIndex, - long[] b, int bFromIndex, - int length) { + public static int mismatch(long[] a, int aFromIndex, + long[] b, int bFromIndex, + int length) { if (length == 0) { return -1; } @@ -506,15 +506,15 @@ class ArraysSupport { // Double - static int mismatch(double[] a, - double[] b, - int length) { + public static int mismatch(double[] a, + double[] b, + int length) { return mismatch(a, 0, b, 0, length); } - static int mismatch(double[] a, int aFromIndex, - double[] b, int bFromIndex, - int length) { + public static int mismatch(double[] a, int aFromIndex, + double[] b, int bFromIndex, + int length) { if (length == 0) { return -1; } diff --git a/test/jdk/java/nio/Buffer/EqualsCompareTest.java b/test/jdk/java/nio/Buffer/EqualsCompareTest.java new file mode 100644 index 00000000000..11cc028f425 --- /dev/null +++ b/test/jdk/java/nio/Buffer/EqualsCompareTest.java @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2017, 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 org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.LongFunction; +import java.util.stream.IntStream; + +/* + * @test + * @bug 8193085 + * @summary tests for buffer equals and compare + * @run testng EqualsCompareTest + */ + +public class EqualsCompareTest { + + // Maximum width in bits + static final int MAX_WIDTH = 512; + + static final Map typeToWidth; + + static { + typeToWidth = new HashMap<>(); + typeToWidth.put(byte.class, Byte.SIZE); + typeToWidth.put(short.class, Short.SIZE); + typeToWidth.put(char.class, Character.SIZE); + typeToWidth.put(int.class, Integer.SIZE); + typeToWidth.put(long.class, Long.SIZE); + typeToWidth.put(float.class, Float.SIZE); + typeToWidth.put(double.class, Double.SIZE); + } + + static int arraySizeFor(Class type) { + assert type.isPrimitive(); + return 4 * MAX_WIDTH / typeToWidth.get(type); + } + + enum BufferKind { + HEAP, + HEAP_VIEW, + DIRECT; + } + + static abstract class BufferType { + final BufferKind k; + final Class bufferType; + final Class elementType; + + final MethodHandle eq; + final MethodHandle cmp; + + final MethodHandle getter; + final MethodHandle setter; + + BufferType(BufferKind k, Class bufferType, Class elementType) { + this.k = k; + this.bufferType = bufferType; + this.elementType = elementType; + + var lookup = MethodHandles.lookup(); + try { + eq = lookup.findVirtual(bufferType, "equals", MethodType.methodType(boolean.class, Object.class)); + cmp = lookup.findVirtual(bufferType, "compareTo", MethodType.methodType(int.class, bufferType)); + + getter = lookup.findVirtual(bufferType, "get", MethodType.methodType(elementType, int.class)); + setter = lookup.findVirtual(bufferType, "put", MethodType.methodType(bufferType, int.class, elementType)); + } + catch (Exception e) { + throw new AssertionError(e); + } + } + + @Override + public String toString() { + return bufferType.getName() + " " + k; + } + + T construct(int length) { + return construct(length, ByteOrder.BIG_ENDIAN); + } + + abstract T construct(int length, ByteOrder bo); + + @SuppressWarnings("unchecked") + T slice(T a, int from, int to) { + return (T) a.position(from).limit(to).slice(); + } + + @SuppressWarnings("unchecked") + E get(T a, int i) { + try { + return (E) getter.invoke(a, i); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + void set(T a, int i, Object v) { + try { + setter.invoke(a, i, convert(v)); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + abstract Object convert(Object o); + + boolean equals(T a, T b) { + try { + return (boolean) eq.invoke(a, b); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + int compare(T a, T b) { + try { + return (int) cmp.invoke(a, b); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + boolean pairWiseEquals(T a, T b) { + if (a.remaining() != b.remaining()) + return false; + int p = a.position(); + for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) + if (!get(a, i).equals(get(b, j))) + return false; + return true; + } + + static class Bytes extends BufferType { + Bytes(BufferKind k) { + super(k, ByteBuffer.class, byte.class); + } + + @Override + ByteBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length).order(bo); + default: + case HEAP_VIEW: + case HEAP: + return ByteBuffer.allocate(length).order(bo); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? ((Integer) o).byteValue() + : o; + } + } + + static class Chars extends BufferType { + Chars(BufferKind k) { + super(k, CharBuffer.class, char.class); + } + + @Override + CharBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Character.BYTES). + order(bo). + asCharBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Character.BYTES). + order(bo). + asCharBuffer(); + default: + case HEAP: + return CharBuffer.allocate(length); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? (char) ((Integer) o).intValue() + : o; + } + + CharBuffer transformToStringBuffer(CharBuffer c) { + char[] chars = new char[c.remaining()]; + c.get(chars); + return CharBuffer.wrap(new String(chars)); + } + } + + static class Shorts extends BufferType { + Shorts(BufferKind k) { + super(k, ShortBuffer.class, short.class); + } + + @Override + ShortBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Short.BYTES). + order(bo). + asShortBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Short.BYTES). + order(bo). + asShortBuffer(); + default: + case HEAP: + return ShortBuffer.allocate(length); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? ((Integer) o).shortValue() + : o; + } + } + + static class Ints extends BufferType { + Ints(BufferKind k) { + super(k, IntBuffer.class, int.class); + } + + @Override + IntBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Integer.BYTES). + order(bo). + asIntBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Integer.BYTES). + order(bo). + asIntBuffer(); + default: + case HEAP: + return IntBuffer.allocate(length); + } + } + + Object convert(Object o) { + return o; + } + } + + static class Floats extends BufferType { + Floats(BufferKind k) { + super(k, FloatBuffer.class, float.class); + } + + @Override + FloatBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Float.BYTES). + order(bo). + asFloatBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Float.BYTES). + order(bo). + asFloatBuffer(); + default: + case HEAP: + return FloatBuffer.allocate(length); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? ((Integer) o).floatValue() + : o; + } + + @Override + boolean pairWiseEquals(FloatBuffer a, FloatBuffer b) { + if (a.remaining() != b.remaining()) + return false; + int p = a.position(); + for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) { + float av = a.get(i); + float bv = b.get(j); + if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv))) + return false; + } + return true; + } + } + + static class Longs extends BufferType { + Longs(BufferKind k) { + super(k, LongBuffer.class, long.class); + } + + @Override + LongBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Long.BYTES). + order(bo). + asLongBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Long.BYTES). + order(bo). + asLongBuffer(); + default: + case HEAP: + return LongBuffer.allocate(length); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? ((Integer) o).longValue() + : o; + } + } + + static class Doubles extends BufferType { + Doubles(BufferKind k) { + super(k, DoubleBuffer.class, double.class); + } + + @Override + DoubleBuffer construct(int length, ByteOrder bo) { + switch (k) { + case DIRECT: + return ByteBuffer.allocateDirect(length * Double.BYTES). + order(bo). + asDoubleBuffer(); + case HEAP_VIEW: + return ByteBuffer.allocate(length * Double.BYTES). + order(bo). + asDoubleBuffer(); + default: + case HEAP: + return DoubleBuffer.allocate(length); + } + } + + @Override + Object convert(Object o) { + return o instanceof Integer + ? ((Integer) o).doubleValue() + : o; + } + + @Override + boolean pairWiseEquals(DoubleBuffer a, DoubleBuffer b) { + if (a.remaining() != b.remaining()) + return false; + int p = a.position(); + for (int i = a.limit() - 1, j = b.limit() - 1; i >= p; i--, j--) { + double av = a.get(i); + double bv = b.get(j); + if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv))) + return false; + } + return true; + } + } + } + + + static Object[][] bufferTypes; + + @DataProvider + public static Object[][] bufferTypesProvider() { + if (bufferTypes == null) { + bufferTypes = new Object[][]{ + {new BufferType.Bytes(BufferKind.HEAP)}, + {new BufferType.Bytes(BufferKind.DIRECT)}, + {new BufferType.Chars(BufferKind.HEAP)}, + {new BufferType.Chars(BufferKind.HEAP_VIEW)}, + {new BufferType.Chars(BufferKind.DIRECT)}, + {new BufferType.Shorts(BufferKind.HEAP)}, + {new BufferType.Shorts(BufferKind.HEAP_VIEW)}, + {new BufferType.Shorts(BufferKind.DIRECT)}, + {new BufferType.Ints(BufferKind.HEAP)}, + {new BufferType.Ints(BufferKind.HEAP_VIEW)}, + {new BufferType.Ints(BufferKind.DIRECT)}, + {new BufferType.Floats(BufferKind.HEAP)}, + {new BufferType.Floats(BufferKind.HEAP_VIEW)}, + {new BufferType.Floats(BufferKind.DIRECT)}, + {new BufferType.Longs(BufferKind.HEAP)}, + {new BufferType.Longs(BufferKind.HEAP_VIEW)}, + {new BufferType.Longs(BufferKind.DIRECT)}, + {new BufferType.Doubles(BufferKind.HEAP)}, + {new BufferType.Doubles(BufferKind.HEAP_VIEW)}, + {new BufferType.Doubles(BufferKind.DIRECT)}, + }; + } + return bufferTypes; + } + + + static Object[][] floatbufferTypes; + + @DataProvider + public static Object[][] floatBufferTypesProvider() { + if (floatbufferTypes == null) { + LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); + LongFunction bToD = Double::longBitsToDouble; + + floatbufferTypes = new Object[][]{ + // canonical and non-canonical NaNs + // If conversion is a signalling NaN it may be subject to conversion to a + // quiet NaN on some processors, even if a copy is performed + // The tests assume that if conversion occurs it does not convert to the + // canonical NaN + new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x7fc00000L, 0x7f800001L, bTof}, + new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x7fc00000L, 0x7f800001L, bTof}, + new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x7fc00000L, 0x7f800001L, bTof}, + new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, + new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, + new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, + + // +0.0 and -0.0 + new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x0L, 0x80000000L, bTof}, + new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x0L, 0x80000000L, bTof}, + new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x0L, 0x80000000L, bTof}, + new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x0L, 0x8000000000000000L, bToD}, + new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x0L, 0x8000000000000000L, bToD}, + new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x0L, 0x8000000000000000L, bToD}, + }; + } + return floatbufferTypes; + } + + + static Object[][] charBufferTypes; + + @DataProvider + public static Object[][] charBufferTypesProvider() { + if (charBufferTypes == null) { + charBufferTypes = new Object[][]{ + {new BufferType.Chars(BufferKind.HEAP)}, + {new BufferType.Chars(BufferKind.HEAP_VIEW)}, + {new BufferType.Chars(BufferKind.DIRECT)}, + }; + } + return charBufferTypes; + } + + + // Tests all primitive buffers + @Test(dataProvider = "bufferTypesProvider") + + void testBuffers(BufferType bufferType) { + // Test with buffers of the same byte order (BE) + BiFunction, Integer, Buffer> constructor = (at, s) -> { + Buffer a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, x % 8); + } + return a; + }; + + testBufferType(bufferType, constructor, constructor); + + // Test with buffers of different byte order + if (bufferType.elementType != byte.class && + (bufferType.k == BufferKind.HEAP_VIEW || + bufferType.k == BufferKind.DIRECT)) { + + BiFunction, Integer, Buffer> leConstructor = (at, s) -> { + Buffer a = at.construct(s, ByteOrder.LITTLE_ENDIAN); + for (int x = 0; x < s; x++) { + at.set(a, x, x % 8); + } + return a; + }; + testBufferType(bufferType, constructor, leConstructor); + } + } + + // Tests float and double buffers with edge-case values (NaN, -0.0, +0.0) + @Test(dataProvider = "floatBufferTypesProvider") + public void testFloatBuffers( + BufferType bufferType, + long rawBitsA, long rawBitsB, + LongFunction bitsToFloat) { + Object av = bitsToFloat.apply(rawBitsA); + Object bv = bitsToFloat.apply(rawBitsB); + + BiFunction, Integer, Buffer> allAs = (at, s) -> { + Buffer b = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(b, x, av); + } + return b; + }; + + BiFunction, Integer, Buffer> allBs = (at, s) -> { + Buffer b = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(b, x, bv); + } + return b; + }; + + BiFunction, Integer, Buffer> halfBs = (at, s) -> { + Buffer b = at.construct(s); + for (int x = 0; x < s / 2; x++) { + at.set(b, x, bv); + } + for (int x = s / 2; x < s; x++) { + at.set(b, x, 1); + } + return b; + }; + + // Sanity check + int size = arraySizeFor(bufferType.elementType); + Assert.assertTrue(bufferType.pairWiseEquals(allAs.apply(bufferType, size), + allBs.apply(bufferType, size))); + Assert.assertTrue(bufferType.equals(allAs.apply(bufferType, size), + allBs.apply(bufferType, size))); + + testBufferType(bufferType, allAs, allBs); + testBufferType(bufferType, allAs, halfBs); + } + + // Tests CharBuffer for region sources and CharSequence sources + @Test(dataProvider = "charBufferTypesProvider") + public void testCharBuffers(BufferType.Chars charBufferType) { + + BiFunction constructor = (at, s) -> { + CharBuffer a = at.construct(s); + for (int x = 0; x < s; x++) { + at.set(a, x, x % 8); + } + return a; + }; + + BiFunction constructorX = constructor. + andThen(charBufferType::transformToStringBuffer); + + testBufferType(charBufferType, constructor, constructorX); + } + + + > + void testBufferType(BT bt, + BiFunction aConstructor, + BiFunction bConstructor) { + int n = arraySizeFor(bt.elementType); + + for (int s : ranges(0, n)) { + B a = aConstructor.apply(bt, s); + B b = bConstructor.apply(bt, s); + + for (int aFrom : ranges(0, s)) { + for (int aTo : ranges(aFrom, s)) { + int aLength = aTo - aFrom; + + B as = aLength != s + ? bt.slice(a, aFrom, aTo) + : a; + + for (int bFrom : ranges(0, s)) { + for (int bTo : ranges(bFrom, s)) { + int bLength = bTo - bFrom; + + B bs = bLength != s + ? bt.slice(b, bFrom, bTo) + : b; + + boolean eq = bt.pairWiseEquals(as, bs); + Assert.assertEquals(bt.equals(as, bs), eq); + Assert.assertEquals(bt.equals(bs, as), eq); + if (eq) { + Assert.assertEquals(bt.compare(as, bs), 0); + Assert.assertEquals(bt.compare(bs, as), 0); + } + else { + int aCb = bt.compare(as, bs); + int bCa = bt.compare(bs, as); + int v = Integer.signum(aCb) * Integer.signum(bCa); + Assert.assertTrue(v == -1); + } + } + } + + if (aLength > 0 && !a.isReadOnly()) { + for (int i = aFrom; i < aTo; i++) { + B c = aConstructor.apply(bt, a.capacity()); + B cs = aLength != s + ? bt.slice(c, aFrom, aTo) + : c; + + // Create common prefix with a length of i - aFrom + bt.set(c, i, -1); + + Assert.assertFalse(bt.equals(c, a)); + + int cCa = bt.compare(cs, as); + int aCc = bt.compare(as, cs); + int v = Integer.signum(cCa) * Integer.signum(aCc); + Assert.assertTrue(v == -1); + } + } + } + } + } + } + + static int[] ranges(int from, int to) { + int width = to - from; + switch (width) { + case 0: + return new int[]{}; + case 1: + return new int[]{from, to}; + case 2: + return new int[]{from, from + 1, to}; + case 3: + return new int[]{from, from + 1, from + 2, to}; + default: + return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to) + .filter(i -> i >= from && i <= to) + .distinct().toArray(); + } + } +} From 7cd32cad8934124b07b96c455eb7813b8abb5d2f Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 20 Dec 2017 22:36:21 -0500 Subject: [PATCH 15/25] 8193838: Update jtreg requiredVersion to 4.2 b11 for JDK 11 and 12 support Reviewed-by: alanb, sspitsyn --- make/conf/jib-profiles.js | 2 +- test/hotspot/jtreg/TEST.ROOT | 2 +- test/jaxp/TEST.ROOT | 2 +- test/jdk/TEST.ROOT | 2 +- test/langtools/TEST.ROOT | 2 +- test/nashorn/TEST.ROOT | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 5066599a924..d01fdaeaa16 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -829,7 +829,7 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "javare", revision: "4.2", - build_number: "b10", + build_number: "b11", checksum_file: "MD5_VALUES", file: "jtreg_bin-4.2.zip", environment_name: "JT_HOME", diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index c7ccaf2f4de..651ebdf6849 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -58,7 +58,7 @@ requires.properties= \ docker.support # Minimum jtreg version -requiredVersion=4.2 b08 +requiredVersion=4.2 b11 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../../ notation to reach them diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index e2f049d3487..4bf95e20e90 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -23,7 +23,7 @@ modules=java.xml groups=TEST.groups # Minimum jtreg version -requiredVersion=4.2 b08 +requiredVersion=4.2 b11 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 0aceb5f4710..aa1807b2941 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -39,7 +39,7 @@ requires.properties= \ vm.cds # Minimum jtreg version -requiredVersion=4.2 b09 +requiredVersion=4.2 b11 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 83af0bdffe2..0260ea81ffe 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness groups=TEST.groups # Minimum jtreg version -requiredVersion=4.2 b08 +requiredVersion=4.2 b11 # Use new module options useNewOptions=true diff --git a/test/nashorn/TEST.ROOT b/test/nashorn/TEST.ROOT index a0e6922a263..be0097f85e3 100644 --- a/test/nashorn/TEST.ROOT +++ b/test/nashorn/TEST.ROOT @@ -8,7 +8,7 @@ keys=intermittent randomness groups=TEST.groups # Minimum jtreg version -requiredVersion=4.2 b08 +requiredVersion=4.2 b11 # Use new module options useNewOptions=true From 755fa4beb78575440418e6752627733171d951d6 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 21 Dec 2017 05:51:38 +0000 Subject: [PATCH 16/25] 8193683: Increase the number of clones in the CloneableDigest Reviewed-by: coffeys, wetmore --- .../sun/security/ssl/HandshakeHash.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java index 2a3775da7df..ba86dd87875 100644 --- a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java +++ b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -108,7 +108,29 @@ final class HandshakeHash { * a hash for the certificate verify message is required. */ HandshakeHash(boolean needCertificateVerify) { - clonesNeeded = needCertificateVerify ? 4 : 3; + // We may rework the code later, but for now we use hard-coded number + // of clones if the underlying MessageDigests are not cloneable. + // + // The number used here is based on the current handshake protocols and + // implementation. It may be changed if the handshake processe gets + // changed in the future, for example adding a new extension that + // requires handshake hash. Please be careful about the number of + // clones if additional handshak hash is required in the future. + // + // For the current implementation, the handshake hash is required for + // the following items: + // . CertificateVerify handshake message (optional) + // . client Finished handshake message + // . server Finished Handshake message + // . the extended Master Secret extension [RFC 7627] + // + // Note that a late call to server setNeedClientAuth dose not update + // the number of clones. We may address the issue later. + // + // Note for safety, we allocate one more clone for the current + // implementation. We may consider it more carefully in the future + // for the exact number or rework the code in a different way. + clonesNeeded = needCertificateVerify ? 5 : 4; } void reserve(ByteBuffer input) { @@ -335,7 +357,8 @@ final class HandshakeHash { if (finMD != null) return; try { - finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2); + // See comment in the contructor. + finMD = CloneableDigest.getDigest(normalizeAlgName(s), 4); } catch (NoSuchAlgorithmException e) { throw new Error(e); } From 3e0afd207dbc5d849228ae8e3603c51811671a17 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Thu, 21 Dec 2017 15:58:45 -0500 Subject: [PATCH 17/25] 8193216: Filer should warn if processors redefine symbols from the classpath or sourcepath Reviewed-by: vromero --- .../tools/javac/processing/JavacFiler.java | 10 +-- .../warnings/TypeAlreadyExists/A.java | 24 +++++++ .../warnings/TypeAlreadyExists/B.java | 26 ++++++++ .../TestProcTypeAlreadyExistsWarning.java | 66 +++++++++++++++++++ .../warnings/TypeAlreadyExists/warn.out | 2 + 5 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/A.java create mode 100644 test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/B.java create mode 100644 test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/TestProcTypeAlreadyExistsWarning.java create mode 100644 test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/warn.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java index a723d811ed5..c410067db8c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java @@ -712,20 +712,20 @@ public class JavacFiler implements Filer, Closeable { } private void checkNameAndExistence(ModuleSymbol mod, String typename, boolean allowUnnamedPackageInfo) throws FilerException { - // TODO: Check if type already exists on source or class path? - // If so, use warning message key proc.type.already.exists checkName(typename, allowUnnamedPackageInfo); - ClassSymbol existing; + ClassSymbol existing = elementUtils.getTypeElement(typename); boolean alreadySeen = aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) || aggregateGeneratedClassNames.contains(Pair.of(mod, typename)) || initialClassNames.contains(typename) || - ((existing = elementUtils.getTypeElement(typename)) != null && - initialInputs.contains(existing.sourcefile)); + (existing != null && initialInputs.contains(existing.sourcefile)); if (alreadySeen) { if (lint) log.warning(Warnings.ProcTypeRecreate(typename)); throw new FilerException("Attempt to recreate a file for type " + typename); } + if (lint && existing != null) { + log.warning("proc.type.already.exists", typename); + } if (!mod.isUnnamed() && !typename.contains(".")) { throw new FilerException("Attempt to create a type in unnamed package of a named module: " + typename); } diff --git a/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/A.java b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/A.java new file mode 100644 index 00000000000..055b50353d8 --- /dev/null +++ b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/A.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, Google Inc. 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. + */ + +public class A {} diff --git a/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/B.java b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/B.java new file mode 100644 index 00000000000..3d5379bb9a7 --- /dev/null +++ b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/B.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017, Google Inc. 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. + */ + +class B { + A a; +} diff --git a/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/TestProcTypeAlreadyExistsWarning.java b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/TestProcTypeAlreadyExistsWarning.java new file mode 100644 index 00000000000..97f9270e1bd --- /dev/null +++ b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/TestProcTypeAlreadyExistsWarning.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, Google Inc. 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 8193216 + * @summary Filer should warn if processors redefine symbols from the classpath or sourcepath + * @library /tools/javac/lib + * @modules java.compiler + * jdk.compiler + * @build JavacTestingAbstractProcessor TestProcTypeAlreadyExistsWarning + * @compile A.java + * @compile/ref=warn.out -XDrawDiagnostics -Xlint:processing -processor TestProcTypeAlreadyExistsWarning B.java + */ + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.IOError; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Set; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.TypeElement; + +@SupportedAnnotationTypes("*") +public class TestProcTypeAlreadyExistsWarning extends JavacTestingAbstractProcessor { + + int round = 0; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + round++; + + if (round == 1) { + try (OutputStream os = + processingEnv.getFiler().createSourceFile("A").openOutputStream()) { + os.write("class A {}".getBytes(UTF_8)); + } catch (IOException e) { + throw new IOError(e); + } + } + + return false; + } +} diff --git a/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/warn.out b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/warn.out new file mode 100644 index 00000000000..aaef118b960 --- /dev/null +++ b/test/langtools/tools/javac/processing/warnings/TypeAlreadyExists/warn.out @@ -0,0 +1,2 @@ +- compiler.warn.proc.type.already.exists: A +1 warning From 64cef020e79997726b344a383d86d5e208cd4fda Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 21 Dec 2017 15:04:45 -0800 Subject: [PATCH 18/25] 8193780: (ref) Remove the undocumented "jdk.lang.ref.disableClearBeforeEnqueue" system property Reviewed-by: alanb --- .../share/classes/java/lang/ref/Reference.java | 11 +---------- test/jdk/java/lang/ref/ReferenceEnqueue.java | 8 +------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index 5125e7cb553..2ead79fb636 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -140,14 +140,6 @@ public abstract class Reference { } } - /* - * system property to disable clearing before enqueuing. - */ - private static final class ClearBeforeEnqueue { - static final boolean DISABLE = - Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue"); - } - /* * Atomically get and clear (set to null) the VM's pending list. */ @@ -299,8 +291,7 @@ public abstract class Reference { * it was not registered with a queue when it was created */ public boolean enqueue() { - if (!ClearBeforeEnqueue.DISABLE) - this.referent = null; + this.referent = null; return this.queue.enqueue(this); } diff --git a/test/jdk/java/lang/ref/ReferenceEnqueue.java b/test/jdk/java/lang/ref/ReferenceEnqueue.java index ddc89fc7f27..c405c5c8a05 100644 --- a/test/jdk/java/lang/ref/ReferenceEnqueue.java +++ b/test/jdk/java/lang/ref/ReferenceEnqueue.java @@ -25,7 +25,6 @@ * @bug 4268317 8132306 8175797 * @summary Test if Reference.enqueue() works properly with GC * @run main ReferenceEnqueue - * @run main/othervm -Djdk.lang.ref.disableClearBeforeEnqueue=true ReferenceEnqueue */ import java.lang.ref.*; @@ -87,8 +86,6 @@ public class ReferenceEnqueue { final ReferenceQueue queue = new ReferenceQueue<>(); final List> refs = new ArrayList<>(); final int iterations = 1000; - final boolean disableClearBeforeEnqueue = - Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue"); ExplicitEnqueue() { this.refs.add(new SoftReference<>(new Object(), queue)); @@ -101,10 +98,7 @@ public class ReferenceEnqueue { if (ref.enqueue() == false) { throw new RuntimeException("Error: enqueue failed"); } - if (disableClearBeforeEnqueue && ref.get() == null) { - throw new RuntimeException("Error: clearing should be disabled"); - } - if (!disableClearBeforeEnqueue && ref.get() != null) { + if (ref.get() != null) { throw new RuntimeException("Error: referent must be cleared"); } } From 8e4276d62870a5217c9bc2fcf52fa2967d222598 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 21 Dec 2017 15:18:49 -0800 Subject: [PATCH 19/25] 8193767: Improve javadoc in ResourceBundle working with modules Reviewed-by: alanb, naoto --- .../classes/java/util/ResourceBundle.java | 227 ++++++++++-------- .../spi/AbstractResourceBundleProvider.java | 32 +-- .../java/util/spi/ResourceBundleProvider.java | 128 ++++++++-- 3 files changed, 245 insertions(+), 142 deletions(-) diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index b361ceefff4..e902b3e45e8 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -204,58 +204,70 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; * known concrete subclasses {@code ListResourceBundle} and * {@code PropertyResourceBundle} are thread-safe. * - *

Resource Bundles in Named Modules

+ *

Resource Bundles and Named Modules

* - * When resource bundles are deployed in named modules, the following - * module-specific requirements and restrictions are applied. + * Resource bundles can be deployed in modules in the following ways: * - *
    - *
  • Code in a named module that calls {@link #getBundle(String, Locale)} - * will locate resource bundles in the caller's module (caller module).
  • - *
  • If resource bundles are deployed in named modules separate from - * the caller module, those resource bundles need to be loaded from service - * providers of {@link ResourceBundleProvider}. The caller module must declare - * "{@code uses}" and the service interface name is the concatenation of the - * package name of the base name, string "{@code .spi.}", the simple class - * name of the base name, and the string "{@code Provider}". The - * bundle provider modules containing resource bundles must - * declare "{@code provides}" with the service interface name and - * its implementation class name. For example, if the base name is - * "{@code com.example.app.MyResources}", the caller module must declare - * "{@code uses com.example.app.spi.MyResourcesProvider;}" and a module containing resource - * bundles must declare "{@code provides com.example.app.spi.MyResourcesProvider - * with com.example.app.internal.MyResourcesProviderImpl;}" - * where {@code com.example.app.internal.MyResourcesProviderImpl} is an - * implementation class of {@code com.example.app.spi.MyResourcesProvider}.
  • - *
  • If you want to use non-standard formats in named modules, such as XML, - * {@link ResourceBundleProvider} needs to be used.
  • - *
  • The {@code getBundle} method with a {@code ClassLoader} may not be able to - * find resource bundles using the given {@code ClassLoader} in named modules. - * The {@code getBundle} method with a {@code Module} can be used, instead.
  • - *
  • {@code ResourceBundle.Control} is not supported in named modules. - * If the {@code getBundle} method with a {@code ResourceBundle.Control} is called - * in a named module, the method will throw an {@code UnsupportedOperationException}. - * Any service providers of {@link ResourceBundleControlProvider} are ignored in - * named modules. - *
  • - *
+ *

Resource bundles together with an application

* - *

ResourceBundleProvider Service Providers

+ * Resource bundles can be deployed together with an application in the same + * module. In that case, the resource bundles are loaded + * by code in the module by calling the {@link #getBundle(String)} + * or {@link #getBundle(String, Locale)} method. * - * The {@code getBundle} factory methods load service providers of - * {@link ResourceBundleProvider}, if available, using {@link ServiceLoader}. - * The service type is designated by - * {@code + ".spi." + + "Provider"}. For - * example, if the base name is "{@code com.example.app.MyResources}", the service - * type is {@code com.example.app.spi.MyResourcesProvider}. - *

- * In named modules, the loaded service providers for the given base name are - * used to load resource bundles. If no service provider is available, or if - * none of the service providers returns a resource bundle and the caller module - * doesn't have its own service provider, the {@code getBundle} factory method - * searches for resource bundles that are local in the caller module and that - * are visible to the class loader of the caller module. The resource bundle - * formats for local module searching are "java.class" and "java.properties". + *

Resource bundles as service providers

+ * + * Resource bundles can be deployed in one or more service provider modules + * and they can be located using {@link ServiceLoader}. + * A {@linkplain ResourceBundleProvider service} interface or class must be + * defined. The caller module declares that it uses the service, the service + * provider modules declare that they provide implementations of the service. + * Refer to {@link ResourceBundleProvider} for developing resource bundle + * services and deploying resource bundle providers. + * The module obtaining the resource bundle can be a resource bundle + * provider itself; in which case this module only locates the resource bundle + * via service provider mechanism. + * + *

A {@linkplain ResourceBundleProvider resource bundle provider} can + * provide resource bundles in any format such XML which replaces the need + * of {@link Control ResourceBundle.Control}. + * + *

Resource bundles in other modules and class path

+ * + * Resource bundles in a named module may be encapsulated so that + * it cannot be located by code in other modules. Resource bundles + * in unnamed modules and class path are open for any module to access. + * Resource bundle follows the resource encapsulation rules as specified + * in {@link Module#getResourceAsStream(String)}. + * + *

The {@code getBundle} factory methods with no {@code Control} parameter + * locate and load resource bundles from + * {@linkplain ResourceBundleProvider service providers}. + * It may continue the search as if calling {@link Module#getResourceAsStream(String)} + * to find the named resource from a given module and calling + * {@link ClassLoader#getResourceAsStream(String)}; refer to + * the specification of the {@code getBundle} method for details. + * Only non-encapsulated resource bundles of "{@code java.class}" + * or "{@code java.properties}" format are searched. + * + *

If the caller module is a + * + * resource bundle provider, it does not fall back to the + * class loader search. + * + *

Resource bundles in automatic modules

+ * + * A common format of resource bundles is in {@linkplain PropertyResourceBundle + * .properties} file format. Typically {@code .properties} resource bundles + * are packaged in a JAR file. Resource bundle only JAR file can be readily + * deployed as an + * automatic module. For example, if the JAR file contains the + * entry "{@code p/q/Foo_ja.properties}" and no {@code .class} entry, + * when resolved and defined as an automatic module, no package is derived + * for this module. This allows resource bundles in {@code .properties} + * format packaged in one or more JAR files that may contain entries + * in the same directory and can be resolved successfully as + * automatic modules. * *

ResourceBundle.Control

* @@ -268,6 +280,14 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle} * factory method for details. * + *

{@link ResourceBundle.Control} is designed for an application deployed + * in an unnamed module, for example to support resource bundles in + * non-standard formats or package localized resources in a non-traditional + * convention. {@link ResourceBundleProvider} is the replacement for + * {@code ResourceBundle.Control} when migrating to modules. + * {@code UnsupportedOperationException} will be thrown when a factory + * method that takes the {@code ResourceBundle.Control} parameter is called. + * *

For the {@code getBundle} factory * methods that take no {@link Control} instance, their default behavior of resource bundle loading @@ -815,14 +835,10 @@ public abstract class ResourceBundle { /** * Gets a resource bundle using the specified base name, the default locale, - * and the caller's class loader. Calling this method is equivalent to calling + * and the caller module. Calling this method is equivalent to calling *

- * getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader()), + * getBundle(baseName, Locale.getDefault(), callerModule), *
- * except that getClassLoader() is run with the security - * privileges of ResourceBundle. - * See {@link #getBundle(String, Locale, ClassLoader) getBundle} - * for a complete description of the search and instantiation strategy. * * @param baseName the base name of the resource bundle, a fully qualified class name * @exception java.lang.NullPointerException @@ -830,6 +846,9 @@ public abstract class ResourceBundle { * @exception MissingResourceException * if no resource bundle for the specified base name can be found * @return a resource bundle for the given base name and the default locale + * + * @see Resource Bundle Search and Loading Strategy + * @see Resource Bundles and Named Modules */ @CallerSensitive public static final ResourceBundle getBundle(String baseName) @@ -887,14 +906,10 @@ public abstract class ResourceBundle { /** * Gets a resource bundle using the specified base name and locale, - * and the caller's class loader. Calling this method is equivalent to calling + * and the caller module. Calling this method is equivalent to calling *
- * getBundle(baseName, locale, this.getClass().getClassLoader()), + * getBundle(baseName, locale, callerModule), *
- * except that getClassLoader() is run with the security - * privileges of ResourceBundle. - * See {@link #getBundle(String, Locale, ClassLoader) getBundle} - * for a complete description of the search and instantiation strategy. * * @param baseName * the base name of the resource bundle, a fully qualified class name @@ -905,6 +920,9 @@ public abstract class ResourceBundle { * @exception MissingResourceException * if no resource bundle for the specified base name can be found * @return a resource bundle for the given base name and locale + * + * @see Resource Bundle Search and Loading Strategy + * @see Resource Bundles and Named Modules */ @CallerSensitive public static final ResourceBundle getBundle(String baseName, @@ -922,19 +940,6 @@ public abstract class ResourceBundle { * getBundle(baseName, Locale.getDefault(), module) * * - *

Resource bundles in named modules may be encapsulated. When - * the resource bundle is loaded from a provider, the caller module - * must have an appropriate uses clause in its module descriptor - * to declare that the module uses implementations of - * {@code + ".spi." + + "Provider"}. - * Otherwise, it will load the resource bundles that are local in the - * given module or that are visible to the class loader of the given module - * (refer to the Resource Bundles in Named Modules - * section for details). - * When the resource bundle is loaded from the specified module, it is - * subject to the encapsulation rules specified by - * {@link Module#getResourceAsStream Module.getResourceAsStream}. - * * @param baseName the base name of the resource bundle, * a fully qualified class name * @param module the module for which the resource bundle is searched @@ -950,6 +955,8 @@ public abstract class ResourceBundle { * @since 9 * @spec JPMS * @see ResourceBundleProvider + * @see Resource Bundle Search and Loading Strategy + * @see Resource Bundles and Named Modules */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Module module) { @@ -963,14 +970,15 @@ public abstract class ResourceBundle { * on behalf of the specified module. * *

Resource bundles in named modules may be encapsulated. When - * the resource bundle is loaded from a provider, the caller module + * the resource bundle is loaded from a + * {@linkplain ResourceBundleProvider service provider}, the caller module * must have an appropriate uses clause in its module descriptor - * to declare that the module uses implementations of - * {@code + ".spi." + + "Provider"}. + * to declare that the module uses of {@link ResourceBundleProvider} + * for the named resource bundle. * Otherwise, it will load the resource bundles that are local in the - * given module or that are visible to the class loader of the given module - * (refer to the Resource Bundles in Named Modules - * section for details). + * given module as if calling {@link Module#getResourceAsStream(String)} + * or that are visible to the class loader of the given module + * as if calling {@link ClassLoader#getResourceAsStream(String)}. * When the resource bundle is loaded from the specified module, it is * subject to the encapsulation rules specified by * {@link Module#getResourceAsStream Module.getResourceAsStream}. @@ -1000,6 +1008,8 @@ public abstract class ResourceBundle { * @return a resource bundle for the given base name and locale in the module * @since 9 * @spec JPMS + * @see Resource Bundle Search and Loading Strategy + * @see Resource Bundles and Named Modules */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) { @@ -1060,28 +1070,25 @@ public abstract class ResourceBundle { * Gets a resource bundle using the specified base name, locale, and class * loader. * - *

This method behaves the same as calling - * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a - * default instance of {@link Control} unless another {@link Control} is - * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the - * description of modifying the default - * behavior. + *

When this method is called from a named module and the given + * loader is the class loader of the caller module, this is equivalent + * to calling: + *

+     * getBundle(baseName, targetLocale, callerModule)
+     * 
* - *

The following describes the default - * behavior. + * otherwise, this is equivalent to calling: + *

+     * getBundle(baseName, targetLocale, loader, control)
+     * 
+ * where {@code control} is the default instance of {@link Control} unless + * a {@code Control} instance is provided by + * {@link ResourceBundleControlProvider} SPI. Refer to the + * description of modifying the default + * behavior. The following describes the default behavior. * *

- * Resource bundles in a named module are private to that module. If - * the caller is in a named module, this method will find resource bundles - * from the service providers of {@link java.util.spi.ResourceBundleProvider} - * if any. Otherwise, it will load the resource bundles that are visible to - * the given {@code loader} (refer to the - * Resource Bundles in Named Modules section - * for details). - * If the caller is in a named module and the given {@code loader} is - * different than the caller's class loader, or if the caller is not in - * a named module, this method will not find resource bundles from named - * modules. + * Resource Bundle Search and Loading Strategy * *

getBundle uses the base name, the specified locale, and * the default locale (obtained from {@link java.util.Locale#getDefault() @@ -1201,7 +1208,7 @@ public abstract class ResourceBundle { * *

Note:The baseName argument should be a fully * qualified class name. However, for compatibility with earlier versions, - * Sun's Java SE Runtime Environments do not verify this, and so it is + * Java SE Runtime Environments do not verify this, and so it is * possible to access PropertyResourceBundles by specifying a * path name (using "/") instead of a fully qualified class name (using * "."). @@ -1248,7 +1255,7 @@ public abstract class ResourceBundle { * * @apiNote If the caller module is a named module and the given * {@code loader} is the caller module's class loader, this method is - * equivalent to {@code getBundle(baseName, locale)}; otherwise, it will not + * equivalent to {@code getBundle(baseName, locale)}; otherwise, it may not * find resource bundles from named modules. * Use {@link #getBundle(String, Locale, Module)} to load resource bundles * on behalf on a specific module instead. @@ -1264,6 +1271,7 @@ public abstract class ResourceBundle { * @since 1.2 * @revised 9 * @spec JPMS + * @see Resource Bundles and Named Modules */ @CallerSensitive public static ResourceBundle getBundle(String baseName, Locale locale, @@ -1278,9 +1286,9 @@ public abstract class ResourceBundle { /** * Returns a resource bundle using the specified base name, target - * locale, class loader and control. Unlike the {@linkplain - * #getBundle(String, Locale, ClassLoader) getBundle - * factory methods with no control argument}, the given + * locale, class loader and control. Unlike the {@link + * #getBundle(String, Locale, ClassLoader) getBundle} + * factory methods with no {@code control} argument, the given * control specifies how to locate and instantiate resource * bundles. Conceptually, the bundle loading process with the given * control is performed in the following steps. @@ -2365,7 +2373,14 @@ public abstract class ResourceBundle { * the callback methods provides the information necessary for the * factory methods to perform the default behavior. - * Note that this class is not supported in named modules. + * + *

{@link ResourceBundle.Control} is designed for an application deployed + * in an unnamed module, for example to support resource bundles in + * non-standard formats or package localized resources in a non-traditional + * convention. {@link ResourceBundleProvider} is the replacement for + * {@code ResourceBundle.Control} when migrating to modules. + * {@code UnsupportedOperationException} will be thrown when a factory + * method that takes the {@code ResourceBundle.Control} parameter is called. * *

In addition to the callback methods, the {@link * #toBundleName(String, Locale) toBundleName} and {@link @@ -2501,8 +2516,8 @@ public abstract class ResourceBundle { * } * * - * @apiNote {@code ResourceBundle.Control} is not supported - * in named modules. If the {@code ResourceBundle.getBundle} method with + * @apiNote {@code ResourceBundle.Control} is not supported + * in named modules. If the {@code ResourceBundle.getBundle} method with * a {@code ResourceBundle.Control} is called in a named module, the method * will throw an {@link UnsupportedOperationException}. Any service providers * of {@link ResourceBundleControlProvider} are ignored in named modules. diff --git a/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java b/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java index 937d233e267..2c543c63bcf 100644 --- a/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java +++ b/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java @@ -45,42 +45,46 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; * *

* Resource bundles can be packaged in one or more - * named modules, bundle modules. The consumer of the + * named modules, service provider modules. The consumer of the * resource bundle is the one calling {@link ResourceBundle#getBundle(String)}. * In order for the consumer module to load a resource bundle * "{@code com.example.app.MyResources}" provided by another module, * it will use the {@linkplain java.util.ServiceLoader service loader} - * mechanism. A service interface named "{@code com.example.app.MyResourcesProvider}" - * must be defined and a bundle provider module will provide an - * implementation class of "{@code com.example.app.MyResourcesProvider}" + * mechanism. A service interface named "{@code com.example.app.spi.MyResourcesProvider}" + * must be defined and a service provider module will provide an + * implementation class of "{@code com.example.app.spi.MyResourcesProvider}" * as follows: * - *


- * import com.example.app.MyResourcesProvider;
+ * 
+ * {@code import com.example.app.spi.MyResourcesProvider;
  * class MyResourcesProviderImpl extends AbstractResourceBundleProvider
  *     implements MyResourcesProvider
  * {
+ *     public MyResourcesProviderImpl() {
+ *         super("java.properties");
+ *     }
+ *     // this provider maps the resource bundle to per-language package
  *     protected String toBundleName(String baseName, Locale locale) {
- *         // return the bundle name per the naming of the resource bundle
- *         :
+ *         return "p." + locale.getLanguage() + "." + baseName;
  *     }
  *
  *     public ResourceBundle getBundle(String baseName, Locale locale) {
- *         // this module only provides bundles in french
+ *         // this module only provides bundles in French
  *         if (locale.equals(Locale.FRENCH)) {
  *              return super.getBundle(baseName, locale);
  *         }
+ *         // otherwise return null
  *         return null;
  *     }
- * }
+ * }}
* - * @see - * Resource Bundles in Named Modules - * @see - * ResourceBundleProvider Service Providers + * Refer to {@link ResourceBundleProvider} for details. * + * @see + * Resource Bundles and Named Modules * @since 9 * @spec JPMS + */ public abstract class AbstractResourceBundleProvider implements ResourceBundleProvider { private static final JavaUtilResourceBundleAccess RB_ACCESS = diff --git a/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java b/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java index 0cb0bccd4a6..62fa501c538 100644 --- a/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java +++ b/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java @@ -29,33 +29,117 @@ import java.util.Locale; import java.util.ResourceBundle; /** - * {@code ResourceBundleProvider} is a provider interface that is used for - * loading resource bundles for named modules. Implementation classes of - * this interface are loaded with {@link java.util.ServiceLoader ServiceLoader} - * during a call to the - * {@link ResourceBundle#getBundle(String, Locale, ClassLoader) - * ResourceBundle.getBundle} method. The provider service type is determined by - * {@code + ".spi." + + "Provider"}. + * {@code ResourceBundleProvider} is a service provider interface for + * resource bundles. It is used by + * {@link ResourceBundle#getBundle(String) ResourceBundle.getBundle} + * factory methods to locate and load the service providers that are deployed as + * modules via {@link java.util.ServiceLoader ServiceLoader}. * - *

- * For example, if the base name is "com.example.app.MyResources", - * {@code com.example.app.spi.MyResourcesProvider} will be the provider service type: - *

{@code
+ * 

Developing resource bundle services

+ * + * A service for a resource bundle of a given {@code baseName} must have + * a fully-qualified class name of the form: + *
+ * {@code + ".spi." + + "Provider"} + *
+ * + * The service type is in a {@code spi} subpackage as it may be packaged in + * a module separate from the resource bundle providers. + * For example, the service for a resource bundle named + * {@code com.example.app.MyResources} must be + * {@code com.example.app.spi.MyResourcesProvider}: + * + *
+ * {@code package com.example.app.spi;
  * public interface MyResourcesProvider extends ResourceBundleProvider {
  * }
- * }
+ * }
* - *

- * This providers's {@link #getBundle(String, Locale) getBundle} method is called - * through the resource bundle loading process instead of {@link - * java.util.ResourceBundle.Control#newBundle(String, Locale, String, ClassLoader, boolean) - * ResourceBundle.Control.newBundle()}. Refer to {@link ResourceBundle} for - * details. + *

Deploying resource bundle service providers

* - * @see - * Resource Bundles in Named Modules - * @see - * ResourceBundleProvider Service Providers + * Resource bundles can be deployed in one or more service providers + * in modules. For example, a provider for a service + * named "{@code com.example.app.spi.MyResourcesProvider}" + * has the following implementation class: + * + *
+ * {@code import com.example.app.spi.MyResourcesProvider;
+ * class MyResourcesProviderImpl extends AbstractResourceBundleProvider
+ *     implements MyResourcesProvider
+ * {
+ *     public MyResourcesProviderImpl() {
+ *         super("java.properties");
+ *     }
+ *     // this provider maps the resource bundle to per-language package
+ *     protected String toBundleName(String baseName, Locale locale) {
+ *         return "p." + locale.getLanguage() + "." + baseName;
+ *     }
+ *
+ *     public ResourceBundle getBundle(String baseName, Locale locale) {
+ *         // this module only provides bundles in French
+ *         if (locale.equals(Locale.FRENCH)) {
+ *              return super.getBundle(baseName, locale);
+ *         }
+ *         // otherwise return null
+ *         return null;
+ *     }
+ * }}
+ * + * This example provides "{@code com.example.app.MyResources}" + * resource bundle of the French locale. Traditionally resource bundles of + * all locales are packaged in the same package as the resource bundle base name. + * When deploying resource bundles in more than one modules and two modules + * containing a package of the same name, split package, + * is not supported, resource bundles in each module can be packaged in + * a different package as shown in this example where this provider packages + * the resource bundles in per-language package, i.e. {@code com.example.app.fr} + * for French locale. + * + *

A provider can provide more than one services, each of which is a service + * for a resource bundle of a different base name. + * + *

{@link AbstractResourceBundleProvider} + * provides the basic implementation for {@code ResourceBundleProvider} + * and a subclass can override the {@link + * AbstractResourceBundleProvider#toBundleName(String, Locale) toBundleName} + * method to return a provider-specific location of the resource to be loaded, + * for example, per-language package. + * A provider can override {@link #getBundle ResourceBundleProvider.getBundle} + * method for example to only search the known supported locales or + * return resource bundles in other formats such as XML. + * + *

The module declaration of this provider module specifies the following + * directive: + *

+ *     provides com.example.app.spi.MyResourcesProvider with com.example.impl.MyResourcesProviderImpl;
+ * 
+ * + *

Obtaining resource bundles from providers

+ * + * The module declaration of the consumer module that calls one of the + * {@code ResourceBundle.getBundle} factory methods to obtain a resource + * bundle from service providers must specify the following directive: + *
+ *     uses com.example.app.spi.MyResourcesProvider;
+ * 
+ * + * {@link ResourceBundle#getBundle(String, Locale) + * ResourceBundle.getBundle("com.example.app.MyResource", locale)} + * locates and loads the providers for {@code com.example.app.spi.MyResourcesProvider} + * service and then invokes {@link #getBundle(String, Locale) + * ResourceBundleProvider.getBundle("com.example.app.MyResource", locale)} to + * find the resource bundle of the given base name and locale. + * If the consumer module is a resource bundle service provider for + * {@code com.example.app.spi.MyResourcesProvider}, {@code ResourceBundle.getBundle} + * will locate resource bundles only from service providers. + * Otherwise, {@code ResourceBundle.getBundle} may continue the search of + * the resource bundle in other modules and class path per the specification + * of the {@code ResourceBundle.getBundle} method being called. + * + * @see AbstractResourceBundleProvider + * @see + * Resource Bundles and Named Modules + * @see java.util.ServiceLoader * @since 9 * @spec JPMS */ From bc0b016989c878ed7bf9263704be61985e0956b5 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 15 Dec 2017 16:51:13 +0100 Subject: [PATCH 20/25] 8193608: Quarantine test/hotspot/jtreg/compiler/codegen/Test6896617.java until JDK-8193479 is fixed Added test to ProblemList.txt Reviewed-by: vlivanov --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index a07b9c9e792..576f582ca41 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -42,6 +42,7 @@ compiler/ciReplay/TestSAServer.java 8029528 generic-all compiler/codecache/stress/OverloadCompileQueueTest.java 8166554 generic-all +compiler/codegen/Test6896617.java 8193479 generic-all compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8140405 generic-all compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java 8158860 generic-all compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all From 5dee8bee7201cb5a74f75bb2c458b30b76559492 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 18 Dec 2017 12:11:01 +0100 Subject: [PATCH 21/25] 8193514: UseMembar should not be obsoleted yet Reviewed-by: dcubed, acorn, mdoerr --- src/hotspot/share/runtime/arguments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index c1427e3aa77..a8ad10d820d 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -497,7 +497,7 @@ static SpecialFlag const special_jvm_flags[] = { { "MaxRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "MinRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, - { "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) }, + { "UseMembar", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "FastTLABRefill", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) }, { "SafepointSpinBeforeYield", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) }, { "DeferThrSuspendLoopCount", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) }, From 4a79a36b6d4eb73d3c24d0086fb23a2468d8c83c Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 19 Dec 2017 17:31:53 -0500 Subject: [PATCH 22/25] 8193840: Add compiler/c2/Test8007294.java to the problem list Reviewed-by: coleenp --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 576f582ca41..23b54e214a6 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -51,6 +51,7 @@ compiler/startup/SmallCodeCacheStartup.java 8134286 generic-all compiler/tiered/LevelTransitionTest.java 8067651 generic-all compiler/types/correctness/CorrectnessTest.java 8066173 generic-all compiler/types/correctness/OffTest.java 8066173 generic-all +compiler/c2/Test8007294.java 8192992 generic-all # aot test intermittently failing in jprt 8175791 compiler/aot/DeoptimizationTest.java 8175791 windows-all From d32979d7714e2119ccb5d59d488c7b1b2102171d Mon Sep 17 00:00:00 2001 From: David Holmes Date: Fri, 22 Dec 2017 15:23:34 -0500 Subject: [PATCH 23/25] 8194071: [Testbug] Update VMDeprecatedOptions test for obsolete/expired options Reviewed-by: hseigel --- .../jtreg/runtime/CommandLine/VMDeprecatedOptions.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index bedcad2e4fe..70d6a636721 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -47,10 +47,6 @@ public class VMDeprecatedOptions { {"InitialRAMFraction", "64"}, {"AssumeMP", "false"}, {"UseMembar", "true"}, - {"FastTLABRefill", "false"}, - {"DeferPollingPageLoopCount", "-1"}, - {"SafepointSpinBeforeYield", "2000"}, - {"DeferThrSuspendLoopCount", "4000"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, @@ -110,6 +106,5 @@ public class VMDeprecatedOptions { testDeprecated(DEPRECATED_OPTIONS); // Make sure that each deprecated option is mentioned in the output. testDeprecatedDiagnostic("UnsyncloadClass", "false"); testDeprecatedDiagnostic("IgnoreUnverifiableClassesDuringDump", "false"); - testDeprecatedExperimental("UseCGroupMemoryLimitForHeap", "true"); } } From 1209c4bcb392f015e7e87b8d585415766065855e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 22 Dec 2017 14:00:03 -0800 Subject: [PATCH 24/25] 8193832: Performance of InputStream.readAllBytes() could be improved Read into a list of fixed-size buffers which are gathered at the end Reviewed-by: alanb, chegar, plevart, jrose, psandoz --- .../share/classes/java/io/InputStream.java | 67 +++++++++++++------ .../jdk/java/io/InputStream/ReadAllBytes.java | 16 ++--- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/java.base/share/classes/java/io/InputStream.java b/src/java.base/share/classes/java/io/InputStream.java index b4d6255034f..8ca91962262 100644 --- a/src/java.base/share/classes/java/io/InputStream.java +++ b/src/java.base/share/classes/java/io/InputStream.java @@ -25,7 +25,9 @@ package java.io; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -229,30 +231,55 @@ public abstract class InputStream implements Closeable { * @since 9 */ public byte[] readAllBytes() throws IOException { - byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; - int capacity = buf.length; - int nread = 0; + List bufs = null; + byte[] result = null; + int total = 0; int n; - for (;;) { - // read to EOF which may read more or less than initial buffer size - while ((n = read(buf, nread, capacity - nread)) > 0) + do { + byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; + int nread = 0; + + // read to EOF which may read more or less than buffer size + while ((n = read(buf, nread, buf.length - nread)) > 0) { nread += n; - - // if the last call to read returned -1, then we're done - if (n < 0) - break; - - // need to allocate a larger buffer - if (capacity <= MAX_BUFFER_SIZE - capacity) { - capacity = capacity << 1; - } else { - if (capacity == MAX_BUFFER_SIZE) - throw new OutOfMemoryError("Required array size too large"); - capacity = MAX_BUFFER_SIZE; } - buf = Arrays.copyOf(buf, capacity); + + if (nread > 0) { + if (MAX_BUFFER_SIZE - total < nread) { + throw new OutOfMemoryError("Required array size too large"); + } + total += nread; + if (result == null) { + result = buf; + } else { + if (bufs == null) { + bufs = new ArrayList<>(); + bufs.add(result); + } + bufs.add(buf); + } + } + } while (n >= 0); // if the last call to read returned -1, then break + + if (bufs == null) { + if (result == null) { + return new byte[0]; + } + return result.length == total ? + result : Arrays.copyOf(result, total); } - return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); + + result = new byte[total]; + int offset = 0; + int remaining = total; + for (byte[] b : bufs) { + int len = Math.min(b.length, remaining); + System.arraycopy(b, 0, result, offset, len); + offset += len; + remaining -= len; + } + + return result; } /** diff --git a/test/jdk/java/io/InputStream/ReadAllBytes.java b/test/jdk/java/io/InputStream/ReadAllBytes.java index c190cd2dd54..a9c536b1909 100644 --- a/test/jdk/java/io/InputStream/ReadAllBytes.java +++ b/test/jdk/java/io/InputStream/ReadAllBytes.java @@ -31,7 +31,7 @@ import jdk.test.lib.RandomFactory; /* * @test - * @bug 8080835 + * @bug 8080835 8193832 * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main ReadAllBytes @@ -47,15 +47,11 @@ public class ReadAllBytes { test(new byte[]{}); test(new byte[]{1, 2, 3}); test(createRandomBytes(1024)); - test(createRandomBytes((1 << 13) - 1)); - test(createRandomBytes((1 << 13))); - test(createRandomBytes((1 << 13) + 1)); - test(createRandomBytes((1 << 15) - 1)); - test(createRandomBytes((1 << 15))); - test(createRandomBytes((1 << 15) + 1)); - test(createRandomBytes((1 << 17) - 1)); - test(createRandomBytes((1 << 17))); - test(createRandomBytes((1 << 17) + 1)); + for (int shift : new int[] {13, 14, 15, 17}) { + for (int offset : new int[] {-1, 0, 1}) { + test(createRandomBytes((1 << shift) + offset)); + } + } } static void test(byte[] expectedBytes) throws IOException { From d1750de1fcb059f0bb1ffea94e5b199df0945119 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Tue, 2 Jan 2018 16:35:04 -0500 Subject: [PATCH 25/25] 8187487: crash with classes with same binary name Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Enter.java | 8 ++++- .../tools/javac/resources/compiler.properties | 6 +++- .../tools/javac/NestedInnerClassNames.out | 2 +- .../CrashWithDuplicateClassNamesTest.java | 20 ++++++++++++ .../CrashWithDuplicateClassNamesTest.out | 3 ++ .../javac/diags/examples/SameBinaryName.java | 32 +++++++++++++++++++ 6 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.java create mode 100644 test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.out create mode 100644 test/langtools/tools/javac/diags/examples/SameBinaryName.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index fe4cb8529de..ec60235650e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -421,6 +421,12 @@ public class Enter extends JCTree.Visitor { // We are seeing a member class. c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner); if (c.owner != owner) { + if (c.name != tree.name) { + log.error(tree.pos(), Errors.SameBinaryName(c.name, tree.name)); + result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType); + tree.sym = (ClassSymbol)result.tsym; + return; + } //anonymous class loaded from a classfile may be recreated from source (see below) //if this class is a member of such an anonymous class, fix the owner: Assert.check(owner.owner.kind != TYP, owner::toString); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 3ca606e2581..e7a3be0cac4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2018, 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 @@ -443,6 +443,10 @@ compiler.err.invalid.repeatable.annotation.not.applicable.in.context=\ compiler.err.duplicate.class=\ duplicate class: {0} +# 0: name, 1: name +compiler.err.same.binary.name=\ + classes: {0} and {1} have the same binary name + compiler.err.duplicate.case.label=\ duplicate case label diff --git a/test/langtools/tools/javac/NestedInnerClassNames.out b/test/langtools/tools/javac/NestedInnerClassNames.out index 2038a29791e..586a618c004 100644 --- a/test/langtools/tools/javac/NestedInnerClassNames.out +++ b/test/langtools/tools/javac/NestedInnerClassNames.out @@ -6,7 +6,7 @@ NestedInnerClassNames.java:46:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.java:59:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames.foo$bar, kindname.class, NestedInnerClassNames NestedInnerClassNames.java:76:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.$bar, kindname.class, NestedInnerClassNames NestedInnerClassNames.java:90:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.bar$bar.bar, kindname.class, NestedInnerClassNames.bar$bar -NestedInnerClassNames.java:109:5: compiler.err.duplicate.class: NestedInnerClassNames.foo.foo +NestedInnerClassNames.java:109:5: compiler.err.same.binary.name: foo, foo$foo NestedInnerClassNames.java:19:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package NestedInnerClassNames.java:28:13: compiler.err.already.defined: kindname.class, foo, kindname.method, m2() NestedInnerClassNames.java:40:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package diff --git a/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.java b/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.java new file mode 100644 index 00000000000..f26846628b0 --- /dev/null +++ b/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.java @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8187487 + * @summary crash with duplicate class name + * @compile/fail/ref=CrashWithDuplicateClassNamesTest.out -XDrawDiagnostics CrashWithDuplicateClassNamesTest.java + */ + +class CrashWithDuplicateClassNamesTest { + static class C1$C2 {} + + static class C1 { + static class C2 {} + } + + static class C3 { + static class C4 {} + } + + static class C3$C4 {} +} diff --git a/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.out b/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.out new file mode 100644 index 00000000000..79cf163acae --- /dev/null +++ b/test/langtools/tools/javac/T8187487/CrashWithDuplicateClassNamesTest.out @@ -0,0 +1,3 @@ +CrashWithDuplicateClassNamesTest.java:12:16: compiler.err.same.binary.name: C1$C2, C2 +CrashWithDuplicateClassNamesTest.java:19:12: compiler.err.same.binary.name: C4, C3$C4 +2 errors diff --git a/test/langtools/tools/javac/diags/examples/SameBinaryName.java b/test/langtools/tools/javac/diags/examples/SameBinaryName.java new file mode 100644 index 00000000000..661d060c5fd --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/SameBinaryName.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +// key: compiler.err.same.binary.name + +class SameBinaryName { + private static final class Foo$Bar {} + + private static final class Foo { + private static final class Bar {} + } +}