diff --git a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk index 268a6b237a1..a8e60309b1c 100644 --- a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk +++ b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk @@ -81,6 +81,7 @@ PROCESSOR_JARS := \ PROCESSOR_PATH := $(call PathList, $(PROCESSOR_JARS)) ADD_EXPORTS := \ + --add-modules jdk.internal.vm.ci \ --add-exports jdk.internal.vm.ci/jdk.vm.ci.aarch64=ALL-UNNAMED \ --add-exports jdk.internal.vm.ci/jdk.vm.ci.amd64=ALL-UNNAMED \ --add-exports jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED \ diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index be04aded810..8d5742c94da 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -105,6 +105,12 @@ #define JAVA_9_VERSION 53 +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"); + if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; +} + void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream, ConstantPool* cp, const int length, @@ -302,6 +308,18 @@ void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const s } break; } + case 19: + case 20: { + // Record that an error occurred in these two cases but keep parsing so + // that ACC_Module can be checked for in the access_flags. Need to + // throw NoClassDefFoundError in that case. + if (_major_version >= JAVA_9_VERSION) { + cfs->guarantee_more(3, CHECK); + cfs->get_u2_fast(); + set_class_bad_constant_seen(tag); + break; + } + } default: { classfile_parse_error("Unknown constant tag %u in class file %s", tag, @@ -359,14 +377,18 @@ PRAGMA_DIAG_POP #endif void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, - ConstantPool* const cp, - const int length, - TRAPS) { + ConstantPool* const cp, + const int length, + TRAPS) { assert(cp != NULL, "invariant"); assert(stream != NULL, "invariant"); // parsing constant pool entries parse_constant_pool_entries(stream, cp, length, CHECK); + if (class_bad_constant_seen() != 0) { + // a bad CP entry has been detected previously so stop parsing and just return. + return; + } int index = 1; // declared outside of loops for portability @@ -1244,6 +1266,10 @@ void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs, } } else if (_major_version >= JAVA_1_5_VERSION) { if (attribute_name == vmSymbols::tag_signature()) { + if (generic_signature_index != 0) { + classfile_parse_error( + "Multiple Signature attributes for field in class file %s", CHECK); + } if (attribute_length != 2) { classfile_parse_error( "Wrong size %u for field's Signature attribute in class file %s", @@ -2565,6 +2591,11 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, } } else if (_major_version >= JAVA_1_5_VERSION) { if (method_attribute_name == vmSymbols::tag_signature()) { + if (generic_signature_index != 0) { + classfile_parse_error( + "Multiple Signature attributes for method in class file %s", + CHECK_NULL); + } if (method_attribute_length != 2) { classfile_parse_error( "Invalid Signature attribute length %u in class file %s", @@ -3284,6 +3315,10 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf } } else if (_major_version >= JAVA_1_5_VERSION) { if (tag == vmSymbols::tag_signature()) { + if (_generic_signature_index != 0) { + classfile_parse_error( + "Multiple Signature attributes in class file %s", CHECK); + } if (attribute_length != 2) { classfile_parse_error( "Wrong Signature attribute length %u in class file %s", @@ -5558,6 +5593,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _protection_domain(protection_domain), _access_flags(), _pub_level(pub_level), + _bad_constant_seen(0), _synthetic_flag(false), _sde_length(false), _sde_buffer(NULL), @@ -5765,8 +5801,14 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, verify_legal_class_modifiers(flags, CHECK); - _access_flags.set_flags(flags); + short bad_constant = class_bad_constant_seen(); + if (bad_constant != 0) { + // Do not throw CFE until after the access_flags are checked because if + // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. + classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, CHECK); + } + _access_flags.set_flags(flags); // This class and superclass _this_class_index = stream->get_u2_fast(); diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index df9ff6848ab..031a7142375 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -122,6 +122,15 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { // for tracing and notifications Publicity _pub_level; + // Used to keep track of whether a constant pool item 19 or 20 is found. These + // correspond to CONSTANT_Module and CONSTANT_Package tags and are not allowed + // in regular class files. For class file version >= 53, a CFE cannot be thrown + // immediately when these are seen because a NCDFE must be thrown if the class's + // access_flags have ACC_MODULE set. But, the access_flags haven't been looked + // at yet. So, the bad constant pool item is cached here. A value of zero + // means that no constant pool item 19 or 20 was found. + short _bad_constant_seen; + // class attributes parsed before the instance klass is created: bool _synthetic_flag; int _sde_length; @@ -161,6 +170,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS); void set_klass(InstanceKlass* instance); + void set_class_bad_constant_seen(short bad_constant); + short class_bad_constant_seen() { return _bad_constant_seen; } void set_class_synthetic_flag(bool x) { _synthetic_flag = x; } void set_class_sourcefile_index(u2 x) { _sourcefile_index = x; } void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; } diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index 169146a607e..c8ab0bbbd2b 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -249,6 +249,13 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { predicate_proj = proj; } } + + // If all the defs of the phi are the same constant, we already have the desired end state. + // Skip the split that would create empty phi and region nodes. + if((r->req() - req_c) == 1) { + return NULL; + } + if (nb_predicate_proj > 1) { // Can happen in case of loop unswitching and when the loop is // optimized out: it's not a loop anymore so we don't care about diff --git a/hotspot/test/ProblemList.txt b/hotspot/test/ProblemList.txt index 31e5703c376..2c657d33705 100644 --- a/hotspot/test/ProblemList.txt +++ b/hotspot/test/ProblemList.txt @@ -79,7 +79,5 @@ serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.ja # :hotspot_misc -testlibrary_tests/ctw/JarDirTest.java 8172457 windows-all - ############################################################################# diff --git a/hotspot/test/runtime/constantPool/ACCModule52.java b/hotspot/test/runtime/constantPool/ACCModule52.java new file mode 100644 index 00000000000..241425076ca --- /dev/null +++ b/hotspot/test/runtime/constantPool/ACCModule52.java @@ -0,0 +1,69 @@ +/* + * 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 jdk.internal.org.objectweb.asm.*; + +/* + * @test + * @summary Test that the JVM ignores ACC_MODULE if it is set for a version + * 52 class file. + * @bug 8175383 + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * @compile -XDignore.symbol.file ACCModule52.java + * @run main ACCModule52 + */ + +public class ACCModule52 { + + static final String CLASS_NAME = "ACCModule52Pkg"; + + public static void main(String[] args) throws Exception { + int ACC_MODULE = 0x8000; + ClassWriter cw = new ClassWriter(0); + cw.visit(Opcodes.V1_8, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, + CLASS_NAME, + null, + "java/lang/Object", + null); + + cw.visitEnd(); + byte[] bytes = cw.toByteArray(); + + + ClassLoader loader = new ClassLoader(ACCModule52.class.getClassLoader()) { + @Override + protected Class> findClass(String cn)throws ClassNotFoundException { + if (cn.equals(CLASS_NAME)) { + Class superClass = super.defineClass(cn, bytes, 0, bytes.length); + } else { + throw new ClassNotFoundException(cn); + } + return null; + } + }; + + Class> clazz = loader.loadClass(CLASS_NAME); + } +} diff --git a/hotspot/test/runtime/constantPool/ConstModule.java b/hotspot/test/runtime/constantPool/ConstModule.java new file mode 100644 index 00000000000..94e577a29ef --- /dev/null +++ b/hotspot/test/runtime/constantPool/ConstModule.java @@ -0,0 +1,255 @@ +/* + * 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 jdk.internal.org.objectweb.asm.*; + +/* + * @test + * @summary Test scenarios for constant pool CONSTANT_Module and CONSTANT_Package + * types, for class file versions 53 and 52, when ACC_MODULE is set and + * not set in the access_flags. + * @bug 8175383 + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * @compile -XDignore.symbol.file ConstModule.java + * @run main ConstModule + */ + +public class ConstModule { + + static final int ACC_MODULE = 0x8000; + static final boolean MODULE_TEST = true; + static final boolean PACKAGE_TEST = false; + static final boolean CFE_EXCEPTION = true; + static final boolean NCDFE_EXCEPTION = false; + + public static void main(String[] args) throws Exception { + + // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for + // class file version 53, when ACC_MODULE is not set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_9, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, + "jdk.fooMod", "FooMod", MODULE_TEST, CFE_EXCEPTION); + + // Test that the JVM throws NCDFE for constant pool CONSTANT_Module type, + // for class file version 53, when ACC_MODULE is set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_9, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, + "jdk.fooModACC", "FooModACC", MODULE_TEST, NCDFE_EXCEPTION); + + // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for + // class file version 52, even when ACC_MODULE is set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_8, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, + "jdk.fooModACC52", "FooModACC52", MODULE_TEST, CFE_EXCEPTION); + + // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for + // class file version 53, when ACC_MODULE is not set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_9, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, + "jdk.fooPkg", "FooPkg", PACKAGE_TEST, CFE_EXCEPTION); + + // Test that the JVM throws NCDFE for constant pool CONSTANT_Package type, + // for class file version 53, when ACC_MODULE is set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_9, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, + "jdk.fooModACC", "FooModACC", PACKAGE_TEST, NCDFE_EXCEPTION); + + // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for + // class file version 52, even when ACC_MODULE is set in the access_flags. + ConstModule.write_and_load(Opcodes.V1_8, + Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, + "jdk.fooModACC52", "FooModACC52", PACKAGE_TEST, CFE_EXCEPTION); + + } + + public static void write_and_load(int version, + int access_flags, + String attr, + String class_name, + boolean module_test, + boolean throwCFE) throws Exception { + ClassWriter cw = new ClassWriter(0); + cw.visit(version, + access_flags, + class_name, + null, + "java/lang/Object", + null); + + if (module_test) + cw.visitAttribute(new TestModuleAttribute(attr)); + else + cw.visitAttribute(new TestPackageAttribute(attr)); + + cw.visitEnd(); + byte[] bytes = cw.toByteArray(); + + + ClassLoader loader = new ClassLoader(ConstModule.class.getClassLoader()) { + @Override + protected Class> findClass(String cn)throws ClassNotFoundException { + if (cn.equals(class_name)) { + try { + Class superClass = super.defineClass(cn, bytes, 0, bytes.length); + throw new RuntimeException("Expected ClassFormatError not thrown"); + } catch (java.lang.ClassFormatError e) { + if (!throwCFE) { + throw new RuntimeException("Unexpected ClassFormatError exception: " + e.getMessage()); + } + if (module_test && !e.getMessage().contains( + "Unknown constant tag 19 in class file")) { + throw new RuntimeException("Wrong ClassFormatError exception: " + e.getMessage()); + } else if (!module_test && !e.getMessage().contains( + "Unknown constant tag 20 in class file")) { + throw new RuntimeException("Wrong ClassFormatError exception: " + e.getMessage()); + } + } catch (java.lang.NoClassDefFoundError f) { + if (throwCFE) { + throw new RuntimeException("Unexpected NoClassDefFoundError exception: " + f.getMessage()); + } + if (!f.getMessage().contains( + "is not a class because access_flag ACC_MODULE is set")) { + throw new RuntimeException("Wrong NoClassDefFoundError exception: " + f.getMessage()); + } + } + } else { + throw new ClassNotFoundException(cn); + } + return null; + } + }; + + Class> clazz = loader.loadClass(class_name); + } + + /** + * ConstModuleAttr attribute. + * + *
{@code
+ *
+ * MainClass_attribute {
+ * // index to CONSTANT_utf8_info structure in constant pool representing
+ * // the string "ConstModuleAttr"
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ *
+ * // index to CONSTANT_Module_info structure
+ * u2 module_name_index
+ * }
+ *
+ * }
+ */
+ public static class TestModuleAttribute extends Attribute {
+ private final String moduleName;
+
+ public TestModuleAttribute(String moduleName) {
+ super("ConstModuleAttr");
+ this.moduleName = moduleName;
+ }
+
+ public TestModuleAttribute() {
+ this(null);
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr,
+ int off,
+ int len,
+ char[] buf,
+ int codeOff,
+ Label[] labels)
+ {
+ String mn = cr.readModule(off, buf);
+ off += 2;
+ return new TestModuleAttribute(mn);
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw,
+ byte[] code,
+ int len,
+ int maxStack,
+ int maxLocals)
+ {
+ ByteVector attr = new ByteVector();
+ attr.putShort(cw.newModule(moduleName));
+ return attr;
+ }
+ }
+
+ /**
+ * ConstPackageAttr attribute.
+ *
+ * {@code
+ *
+ * MainClass_attribute {
+ * // index to CONSTANT_utf8_info structure in constant pool representing
+ * // the string "ConstPackageAttr"
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ *
+ * // index to CONSTANT_Package_info structure
+ * u2 module_name_index
+ * }
+ *
+ * }
+ */
+ public static class TestPackageAttribute extends Attribute {
+ private final String packageName;
+
+ public TestPackageAttribute(String packageName) {
+ super("ConstPackageAttr");
+ this.packageName = packageName;
+ }
+
+ public TestPackageAttribute() {
+ this(null);
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr,
+ int off,
+ int len,
+ char[] buf,
+ int codeOff,
+ Label[] labels)
+ {
+ String mn = cr.readPackage(off, buf);
+ off += 2;
+ return new TestPackageAttribute(mn);
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw,
+ byte[] code,
+ int len,
+ int maxStack,
+ int maxLocals)
+ {
+ ByteVector attr = new ByteVector();
+ attr.putShort(cw.newPackage(packageName));
+ return attr;
+ }
+ }
+}
diff --git a/hotspot/test/runtime/duplAttributes/DupSignatureAttrs.jcod b/hotspot/test/runtime/duplAttributes/DupSignatureAttrs.jcod
new file mode 100644
index 00000000000..b43db02f5b5
--- /dev/null
+++ b/hotspot/test/runtime/duplAttributes/DupSignatureAttrs.jcod
@@ -0,0 +1,615 @@
+/*
+ * 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.
+ */
+
+// Class containing duplicate Signature attributes. Loading it should cause a
+// ClassFormatError exception.
+class DupClassSigAttrs {
+ 0xCAFEBABE;
+ 0; // minor version
+ 53; // version
+ [33] { // Constant Pool
+ ; // first element is empty
+ Method #6 #17; // #1 at 0x0A
+ Field #18 #19; // #2 at 0x0F
+ String #20; // #3 at 0x14
+ Method #21 #22; // #4 at 0x17
+ class #23; // #5 at 0x1C
+ class #24; // #6 at 0x1F
+ Utf8 "