diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp index ede8cdaf32c..20856ef44b7 100644 --- a/src/hotspot/share/classfile/stackMapTable.cpp +++ b/src/hotspot/share/classfile/stackMapTable.cpp @@ -259,12 +259,12 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { NameAndSig tmp(name, sig); if (!_prev_frame->assert_unset_fields()->contains(tmp)) { - ResourceMark rm(THREAD); - log_info(verification)("Field %s%s is not found among initial strict instance fields", name->as_C_string(), sig->as_C_string()); + log_info(verification)("NameAndType %s%s(CP index: %d) is not found among initial strict instance fields", name->as_C_string(), sig->as_C_string(), index); StackMapFrame::print_strict_fields(_prev_frame->assert_unset_fields()); _prev_frame->verifier()->verify_error( ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), "Strict fields not a subset of initial strict instance fields: %s:%s", name->as_C_string(), sig->as_C_string()); + return nullptr; } else { new_fields->put(tmp, false); } @@ -277,6 +277,7 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { _prev_frame->verifier()->verify_error( ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), "Cannot have uninitialized strict fields after class initialization"); + return nullptr; } // Continue reading frame data @@ -284,6 +285,7 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { _prev_frame->verifier()->verify_error( ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), "Early larval frame must be followed by a base frame"); + return nullptr; } frame_type = _stream->get_u1(CHECK_NULL); @@ -291,6 +293,7 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { _prev_frame->verifier()->verify_error( ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), "Early larval frame must be followed by a base frame"); + return nullptr; } } diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index b492ce42494..06b40e3110c 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -130,6 +130,7 @@ containers/docker/TestJcmdWithSideCar.java 8341518 linux-x64 # Valhalla runtime/AccModule/ConstModule.java 8294051 generic-all runtime/valhalla/inlinetypes/CircularityTest.java 8349037 generic-all +runtime/valhalla/inlinetypes/verifier/StrictInstanceFieldsTest.java 8357141 generic-all compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java 8357785 generic-all # Valhalla + COH diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild.jasm new file mode 100644 index 00000000000..d2df553e97e --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild.jasm @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025, 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 BadChild extends Parent { + @Strict int x; + @Strict int y; + + BadChild() { + y = 1; + super(); // FAIL: Strict field x must be set before this call + x = 1; + } +} +*/ + +identity class BadChild extends Parent version 69:65535 +{ + @-jdk/internal/vm/annotation/Strict { } + strict Field x:I; + @-jdk/internal/vm/annotation/Strict { } + strict Field y:I; + + Method "":"()V" + stack 4 locals 1 + { + aload_0; + aload_0; + iconst_1; + dup_x1; + putfield Field y:"I"; + aload_0; + invokespecial Method Parent."":"()V"; // FAIL: Strict field x must be set before this call + putfield Field x:"I"; + return; + } + + Method get_x:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field x:"I"; + ireturn; + } + + Method get_y:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field y:"I"; + ireturn; + } +} // end Class BadChild diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild1.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild1.jasm new file mode 100644 index 00000000000..6b49d52d3a5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/BadChild1.jasm @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025, 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 BadChild extends Parent { + @Strict int x; + @Strict int y; + + BadChild() { + x = 1; + super(); // FAIL: Strict field y must be set before this call + y = 1; + } +} +*/ + +identity class BadChild1 extends Parent version 69:65535 +{ + @-jdk/internal/vm/annotation/Strict { } + strict Field x:I; + @-jdk/internal/vm/annotation/Strict { } + strict Field y:I; + + Method "":"()V" + stack 4 locals 1 + { + aload_0; + aload_0; + iconst_1; + dup_x1; + putfield Field x:"I"; + aload_0; + invokespecial Method Parent."":"()V"; // FAIL: Strict field y must be set before this call + putfield Field y:"I"; + return; + } + + Method get_x:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field x:"I"; + ireturn; + } + + Method get_y:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field y:"I"; + ireturn; + } +} // end Class BadChild1 diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/ControlFlowChildBad.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/ControlFlowChildBad.jasm new file mode 100644 index 00000000000..abf1a4d7012 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/ControlFlowChildBad.jasm @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2025, 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 ControlFlowChild extends Parent { + @Strict int x; + @Strict int y; + + ControlFlowChild(boolean a, boolean b) { + if (a) { // FAIL: Strict field x never set on this path + if (b) { + y = 1; + } else { + y = 2; + } + } else { + x = y = 3; + } + super(); // + } +} +*/ + +identity class ControlFlowChildBad extends Parent version 69:65535 +{ + @-jdk/internal/vm/annotation/Strict { } + strict Field x:I; + @-jdk/internal/vm/annotation/Strict { } + strict Field y:I; + + Method "":"(ZZ)V" + stack 4 locals 3 + { + iload_1; + ifeq L29; + aload_0; + iconst_1; + putfield Field y:"I"; + iload_2; + ifeq L21; + aload_0; + iconst_1; + putfield Field y:"I"; + goto L39; + L21: stack_frame_type early_larval; + unset_fields y:"I"; + frame_type same; + aload_0; + iconst_2; + putfield Field y:"I"; + goto L39; // FAIL: Strict field x never set on this path + L29: stack_frame_type early_larval; + unset_fields x:"I", + y:"I"; + frame_type same; + aload_0; + aload_0; + iconst_3; + dup_x1; + putfield Field y:"I"; + putfield Field x:"I"; + L39: stack_frame_type early_larval; + unset_fields; + frame_type same; + aload_0; + invokespecial Method Parent."":"()V"; + return; + } + + Method get_x:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field x:"I"; + ireturn; + } + + Method get_y:"()I" + stack 1 locals 1 + { + aload_0; + getfield Field y:"I"; + ireturn; + } +} // end Class ControlFlowChildBad diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EndsInEarlyLarval.jcod b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EndsInEarlyLarval.jcod new file mode 100644 index 00000000000..75277882019 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/EndsInEarlyLarval.jcod @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2025, 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 EndsInEarlyLarval extends Parent { + @Strict + int x; + @Strict + int y; + + EndsInEarlyLarval(boolean a, boolean b) { + if (a) { + x = 1; + if (b) { + y = 1; + } else { + y = 2; + } + } else { + x = y = 3; + } + super(); + } +} +*/ + +class EndsInEarlyLarval { + 0xCAFEBABE; + 65535; // minor version + 69; // version + [] { // Constant Pool + ; // first element is empty + Field #2 #3; // #1 + Class #4; // #2 + NameAndType #5 #6; // #3 + Utf8 "EndsInEarlyLarval"; // #4 + Utf8 "x"; // #5 + Utf8 "I"; // #6 + Field #2 #8; // #7 + NameAndType #9 #6; // #8 + Utf8 "y"; // #9 + Method #11 #12; // #10 + Class #13; // #11 + NameAndType #14 #15; // #12 + Utf8 "Parent"; // #13 + Utf8 ""; // #14 + Utf8 "()V"; // #15 + Method #2 #17; // #16 + NameAndType #18 #19; // #17 + Utf8 "get_x"; // #18 + Utf8 "()I"; // #19 + Method #2 #21; // #20 + NameAndType #22 #19; // #21 + Utf8 "get_y"; // #22 + Method #11 #24; // #23 + NameAndType #25 #26; // #24 + Utf8 "toString"; // #25 + Utf8 "()Ljava/lang/String;"; // #26 + InvokeDynamic 0s #28; // #27 + NameAndType #29 #30; // #28 + Utf8 "makeConcatWithConstants"; // #29 + Utf8 "(IILjava/lang/String;)Ljava/lang/String;"; // #30 + Utf8 "RuntimeInvisibleAnnotations"; // #31 + Utf8 "Ljdk/internal/vm/annotation/Strict;"; // #32 + Utf8 "(ZZ)V"; // #33 + Utf8 "Code"; // #34 + Utf8 "LineNumberTable"; // #35 + Utf8 "StackMapTable"; // #36 + Utf8 "SourceFile"; // #37 + Utf8 "StrictInstanceFieldsTest.java"; // #38 + Utf8 "BootstrapMethods"; // #39 + String #41; // #40 + Utf8 "x: \u0001\ny: \u0001\n\u0001"; // #41 + MethodHandle 6b #43; // #42 + Method #44 #45; // #43 + Class #46; // #44 + NameAndType #29 #47; // #45 + Utf8 "java/lang/invoke/StringConcatFactory"; // #46 + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"; // #47 + Utf8 "InnerClasses"; // #48 + Class #50; // #49 + Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #50 + Class #52; // #51 + Utf8 "java/lang/invoke/MethodHandles"; // #52 + Utf8 "Lookup"; // #53 + } + + 0x0020; // access + #2; // this_cpx + #11; // super_cpx + + [] { // Interfaces + } // end of Interfaces + + [] { // Fields + { // field + 0x0800; // access + #5; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + ; + { // field + 0x0800; // access + #9; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + } // end of Fields + + [] { // Methods + { // method + 0x0000; // access + #14; // name_index + #33; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 4; // max_stack + 3; // max_locals + Bytes[]{ + 0x1B 0x99 0x00 0x1C 0x2A 0x04 0xB5 0x00 0x01 0x1C 0x99 0x00; + 0x0B 0x2A 0x04 0xB5 0x00 0x07 0xA7 0x00 0x15 0x2A 0x05 0xB5; + 0x00 0x07 0xA7 0x00 0x0D 0x2A 0x2A 0x06 0x5A 0xB5 0x00 0x07; + 0xB5 0x00 0x01 0x2A 0xB7 0x00 0x0A 0xB1; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 121; + 4 122; + 9 123; + 13 124; + 21 126; + 29 129; + 39 131; + 43 132; + } + } // end of LineNumberTable + ; + Attr(#36) { // StackMapTable + [] { // + 246b, []{#8}, { // early_larval_frame + 21b; // same + }; + 246b, []{#3; #8}, { // early_larval_frame + 7b; // same_frame + }; + 246b, []{}, { // FAIL: early_larval_frame with no base frame + }; + } + } // end of StackMapTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #18; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x01 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 134; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #22; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x07 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 135; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0001; // access + #25; // name_index + #26; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 3; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB6 0x00 0x10 0x2A 0xB6 0x00 0x14 0x2A 0xB7 0x00 0x17; + 0xBA 0x00 0x1B 0x00 0x00 0xB0; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 139; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + } // end of Methods + + [] { // Attributes + Attr(#37) { // SourceFile + #38; + } // end of SourceFile + ; + Attr(#39) { // BootstrapMethods + [] { // bootstrap_methods + { // bootstrap_method + #42; // bootstrap_method_ref + [] { // bootstrap_arguments + #40; + } // bootstrap_arguments + } // bootstrap_method + } + } // end of BootstrapMethods + ; + Attr(#48) { // InnerClasses + [] { // classes + #49 #51 #53 57; + } + } // end of InnerClasses + } // end of Attributes +} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/NestedEarlyLarval.jcod b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/NestedEarlyLarval.jcod new file mode 100644 index 00000000000..0947d5ab2f8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/NestedEarlyLarval.jcod @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2025, 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 NestedEarlyLarval { + 0xCAFEBABE; + 65535; // minor version + 69; // version + [] { // Constant Pool + ; // first element is empty + Field #2 #3; // #1 + Class #4; // #2 + NameAndType #5 #6; // #3 + Utf8 "NestedEarlyLarval"; // #4 + Utf8 "x"; // #5 + Utf8 "I"; // #6 + Field #2 #8; // #7 + NameAndType #9 #6; // #8 + Utf8 "y"; // #9 + Method #11 #12; // #10 + Class #13; // #11 + NameAndType #14 #15; // #12 + Utf8 "Parent"; // #13 + Utf8 ""; // #14 + Utf8 "()V"; // #15 + Method #2 #17; // #16 + NameAndType #18 #19; // #17 + Utf8 "get_x"; // #18 + Utf8 "()I"; // #19 + Method #2 #21; // #20 + NameAndType #22 #19; // #21 + Utf8 "get_y"; // #22 + Method #11 #24; // #23 + NameAndType #25 #26; // #24 + Utf8 "toString"; // #25 + Utf8 "()Ljava/lang/String;"; // #26 + InvokeDynamic 0s #28; // #27 + NameAndType #29 #30; // #28 + Utf8 "makeConcatWithConstants"; // #29 + Utf8 "(IILjava/lang/String;)Ljava/lang/String;"; // #30 + Utf8 "RuntimeInvisibleAnnotations"; // #31 + Utf8 "Ljdk/internal/vm/annotation/Strict;"; // #32 + Utf8 "(ZZ)V"; // #33 + Utf8 "Code"; // #34 + Utf8 "LineNumberTable"; // #35 + Utf8 "StackMapTable"; // #36 + Utf8 "SourceFile"; // #37 + Utf8 "StrictInstanceFieldsTest.java"; // #38 + Utf8 "BootstrapMethods"; // #39 + String #41; // #40 + Utf8 "x: \u0001\ny: \u0001\n\u0001"; // #41 + MethodHandle 6b #43; // #42 + Method #44 #45; // #43 + Class #46; // #44 + NameAndType #29 #47; // #45 + Utf8 "java/lang/invoke/StringConcatFactory"; // #46 + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"; // #47 + Utf8 "InnerClasses"; // #48 + Class #50; // #49 + Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #50 + Class #52; // #51 + Utf8 "java/lang/invoke/MethodHandles"; // #52 + Utf8 "Lookup"; // #53 + } + + 0x0020; // access + #2; // this_cpx + #11; // super_cpx + + [] { // Interfaces + } // end of Interfaces + + [] { // Fields + { // field + 0x0800; // access + #5; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + ; + { // field + 0x0800; // access + #9; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + } // end of Fields + + [] { // Methods + { // method + 0x0000; // access + #14; // name_index + #33; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 4; // max_stack + 3; // max_locals + Bytes[]{ + 0x1B 0x99 0x00 0x1C 0x2A 0x04 0xB5 0x00 0x01 0x1C 0x99 0x00; + 0x0B 0x2A 0x04 0xB5 0x00 0x07 0xA7 0x00 0x15 0x2A 0x05 0xB5; + 0x00 0x07 0xA7 0x00 0x0D 0x2A 0x2A 0x06 0x5A 0xB5 0x00 0x07; + 0xB5 0x00 0x01 0x2A 0xB7 0x00 0x0A 0xB1; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 121; + 4 122; + 9 123; + 13 124; + 21 126; + 29 129; + 39 131; + 43 132; + } + } // end of LineNumberTable + ; + Attr(#36) { // StackMapTable + [] { // + 246b, []{#8}, { // early_larval_frame + 246b; // early_larval_frame, illegal + }; + 246b, []{#3; #8}, { // early_larval_frame + 7b; // same_frame + }; + 246b, []{}, { // early_larval_frame + 9b; // same_frame + }; + } + } // end of StackMapTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #18; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x01 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 134; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #22; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x07 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 135; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0001; // access + #25; // name_index + #26; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 3; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB6 0x00 0x10 0x2A 0xB6 0x00 0x14 0x2A 0xB7 0x00 0x17; + 0xBA 0x00 0x1B 0x00 0x00 0xB0; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 139; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + } // end of Methods + + [] { // Attributes + Attr(#37) { // SourceFile + #38; + } // end of SourceFile + ; + Attr(#39) { // BootstrapMethods + [] { // bootstrap_methods + { // bootstrap_method + #42; // bootstrap_method_ref + [] { // bootstrap_arguments + #40; + } // bootstrap_arguments + } // bootstrap_method + } + } // end of BootstrapMethods + ; + Attr(#48) { // InnerClasses + [] { // classes + #49 #51 #53 57; + } + } // end of InnerClasses + } // end of Attributes +} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFieldsNotSubset.jcod b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFieldsNotSubset.jcod new file mode 100644 index 00000000000..6e11698997c --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFieldsNotSubset.jcod @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2025, 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 StrictFieldsNotSubset extends Parent { + @Strict + int x; + @Strict + int y; + + StrictFieldsNotSubset(boolean a, boolean b) { + if (a) { + x = 1; + if (b) { + y = 1; + } else { + y = 2; + } + } else { + x = y = 3; + } + super(); + } +} +*/ + +class StrictFieldsNotSubset { + 0xCAFEBABE; + 65535; // minor version + 69; // version + [] { // Constant Pool + ; // first element is empty + Field #2 #3; // #1 + Class #4; // #2 + NameAndType #5 #6; // #3 + Utf8 "StrictFieldsNotSubset"; // #4 + Utf8 "x"; // #5 + Utf8 "I"; // #6 + Field #2 #8; // #7 + NameAndType #9 #6; // #8 + Utf8 "y"; // #9 + Method #11 #12; // #10 + Class #13; // #11 + NameAndType #14 #15; // #12 + Utf8 "Parent"; // #13 + Utf8 ""; // #14 + Utf8 "()V"; // #15 + Method #2 #17; // #16 + NameAndType #18 #19; // #17 + Utf8 "get_x"; // #18 + Utf8 "()I"; // #19 + Method #2 #21; // #20 + NameAndType #22 #19; // #21 + Utf8 "get_y"; // #22 + Method #11 #24; // #23 + NameAndType #25 #26; // #24 + Utf8 "toString"; // #25 + Utf8 "()Ljava/lang/String;"; // #26 + InvokeDynamic 0s #28; // #27 + NameAndType #29 #30; // #28 + Utf8 "makeConcatWithConstants"; // #29 + Utf8 "(IILjava/lang/String;)Ljava/lang/String;"; // #30 + Utf8 "RuntimeInvisibleAnnotations"; // #31 + Utf8 "Ljdk/internal/vm/annotation/Strict;"; // #32 + Utf8 "(ZZ)V"; // #33 + Utf8 "Code"; // #34 + Utf8 "LineNumberTable"; // #35 + Utf8 "StackMapTable"; // #36 + Utf8 "SourceFile"; // #37 + Utf8 "StrictInstanceFieldsTest.java"; // #38 + Utf8 "BootstrapMethods"; // #39 + String #41; // #40 + Utf8 "x: \u0001\ny: \u0001\n\u0001"; // #41 + MethodHandle 6b #43; // #42 + Method #44 #45; // #43 + Class #46; // #44 + NameAndType #29 #47; // #45 + Utf8 "java/lang/invoke/StringConcatFactory"; // #46 + Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"; // #47 + Utf8 "InnerClasses"; // #48 + Class #50; // #49 + Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #50 + Class #52; // #51 + Utf8 "java/lang/invoke/MethodHandles"; // #52 + Utf8 "Lookup"; // #53 + } + + 0x0020; // access + #2; // this_cpx + #11; // super_cpx + + [] { // Interfaces + } // end of Interfaces + + [] { // Fields + { // field + 0x0800; // access + #5; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + ; + { // field + 0x0800; // access + #9; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#31) { // RuntimeInvisibleAnnotations + [] { // annotations + { // annotation + #32; + [] { // element_value_pairs + } // element_value_pairs + } // annotation + } + } // end of RuntimeInvisibleAnnotations + } // end of Attributes + } + } // end of Fields + + [] { // Methods + { // method + 0x0000; // access + #14; // name_index + #33; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 4; // max_stack + 3; // max_locals + Bytes[]{ + 0x1B 0x99 0x00 0x1C 0x2A 0x04 0xB5 0x00 0x01 0x1C 0x99 0x00; + 0x0B 0x2A 0x04 0xB5 0x00 0x07 0xA7 0x00 0x15 0x2A 0x05 0xB5; + 0x00 0x07 0xA7 0x00 0x0D 0x2A 0x2A 0x06 0x5A 0xB5 0x00 0x07; + 0xB5 0x00 0x01 0x2A 0xB7 0x00 0x0A 0xB1; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 121; + 4 122; + 9 123; + 13 124; + 21 126; + 29 129; + 39 131; + 43 132; + } + } // end of LineNumberTable + ; + Attr(#36) { // StackMapTable + [] { // + 246b, []{#8; #12}, { // FAIL: early_larval_frame contains NameAndType not present in original list of strict fields + 21b; // same + }; + 246b, []{#3; #8}, { // early_larval_frame + 7b; // same_frame + }; + 246b, []{}, { // early_larval_frame + 9b; // same_frame + }; + } + } // end of StackMapTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #18; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x01 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 134; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0000; // access + #22; // name_index + #19; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB4 0x00 0x07 0xAC; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 135; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + ; + { // method + 0x0001; // access + #25; // name_index + #26; // descriptor_index + [] { // Attributes + Attr(#34) { // Code + 3; // max_stack + 1; // max_locals + Bytes[]{ + 0x2A 0xB6 0x00 0x10 0x2A 0xB6 0x00 0x14 0x2A 0xB7 0x00 0x17; + 0xBA 0x00 0x1B 0x00 0x00 0xB0; + } + [] { // Traps + } // end of Traps + [] { // Attributes + Attr(#35) { // LineNumberTable + [] { // line_number_table + 0 139; + } + } // end of LineNumberTable + } // end of Attributes + } // end of Code + } // end of Attributes + } + } // end of Methods + + [] { // Attributes + Attr(#37) { // SourceFile + #38; + } // end of SourceFile + ; + Attr(#39) { // BootstrapMethods + [] { // bootstrap_methods + { // bootstrap_method + #42; // bootstrap_method_ref + [] { // bootstrap_arguments + #40; + } // bootstrap_arguments + } // bootstrap_method + } + } // end of BootstrapMethods + ; + Attr(#48) { // InnerClasses + [] { // classes + #49 #51 #53 57; + } + } // end of InnerClasses + } // end of Attributes +} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFinalInstanceFieldsTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFinalInstanceFieldsTest.java deleted file mode 100644 index 1e63f424d68..00000000000 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictFinalInstanceFieldsTest.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2025, 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 - * @enablePreview - * @compile --add-exports=java.base/jdk.internal.vm.annotation=ALL-UNNAMED -XDgenerateEarlyLarvalFrame -XDnoLocalProxyVars StrictFinalInstanceFieldsTest.java - * @run main/othervm -Xlog:verification StrictFinalInstanceFieldsTest - */ - -import jdk.internal.vm.annotation.Strict; - -public class StrictFinalInstanceFieldsTest { - public static void main(String[] args) { - // Base case - Child c = new Child(); - System.out.println(c); - - // Field not initialized before super call - /* - // javac is flagging the error at compile time - try { - BadChild0 bc0 = new BadChild0(); - System.out.println(bc0); - throw new RuntimeException("Should fail verification"); - } catch (java.lang.VerifyError e) { - if (!e.getMessage().contains("All strict final fields must be initialized before super()")) { - throw new RuntimeException("wrong exception: " + e.getMessage()); - } - e.printStackTrace(); - } - - // Field not initialized before super call - try { - BadChild1 bc1 = new BadChild1(); - System.out.println(bc1); - throw new RuntimeException("Should fail verification"); - } catch (java.lang.VerifyError e) { - if (!e.getMessage().contains("All strict final fields must be initialized before super()")) { - throw new RuntimeException("wrong exception: " + e.getMessage()); - } - e.printStackTrace(); - } - */ - - // Test constructor with control flow. Should pass - Child1 c1 = new Child1(true, false); - System.out.println(c1); - - // Test constructor with control flow and nested constructor calls. Should pass - Child1 c1_2 = new Child1(); - System.out.println(c1_2); - - // Test assignment in conditional. Should pass - Child2 c2 = new Child2(); - System.out.println(c2); - - // Test constructor with control flow in switch case. Should pass - Child3 c3 = new Child3(2); - System.out.println(c3); - - System.out.println("Passed"); - } -} - -class Parent { - int z; - - Parent() { - z = 0; - } - - int get_z() { return z; } - - @Override - public String toString() { - return "z: " + get_z(); - } -} - -class Child extends Parent { - - @Strict - final int x; - @Strict - final int y; - - Child() { - x = y = 1; - super(); - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} - -class BadChild0 extends Parent { - - @Strict - final int x; - @Strict - final int y; - - // Should fail with "All strict final fields must be initialized before super()" - BadChild0() { - x = 1; - y = 1; - super(); - // was y = 1; - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} - -class BadChild1 extends Parent { - - @Strict - final int x; - @Strict - final int y; - - // Should fail with "All strict final fields must be initialized before super()" - BadChild1() { - y = 1; - x = 1; - super(); - // was x = 1; - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} - -class Child1 extends Parent { - - @Strict - final int x; - @Strict - final int y; - - Child1(boolean a, boolean b) { - if (a) { - x = 1; - if (b) { - y = 1; - } else { - y = 2; - } - } else { - x = y = 3; - } - super(); - } - - Child1() { - this(true, true); - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} - -class Child2 extends Parent { - - @Strict - final int x; - @Strict - final int y; - - Child2() { - if ((x=1) == 1) { - y = 1; - } else { - y = 2; - } - super(); - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} - -class Child3 extends Parent { - - @Strict - final int x; - @Strict - final int y; - - Child3(int n) { - switch(n) { - case 0: - x = y = 0; - break; - case 1: - x = y = 1; - break; - case 2: - x = y = 2; - break; - default: - x = y = 100; - break; - } - super(); - } - - int get_x() { return x; } - int get_y() { return y; } - - @Override - public String toString() { - return "x: " + get_x() + "\n" + "y: " + get_y() + "\n" + super.toString(); - } -} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictInstanceFieldsTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictInstanceFieldsTest.java new file mode 100644 index 00000000000..d3065d1da86 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/StrictInstanceFieldsTest.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2025, 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 + * @enablePreview + * @compile BadChild.jasm + * BadChild1.jasm + * ControlFlowChildBad.jasm + * TryCatchChildBad.jasm + * NestedEarlyLarval.jcod + * EndsInEarlyLarval.jcod + * StrictFieldsNotSubset.jcod + * @compile --add-exports=java.base/jdk.internal.vm.annotation=ALL-UNNAMED -XDgenerateEarlyLarvalFrame -XDnoLocalProxyVars StrictInstanceFieldsTest.java + * @run main/othervm -Xlog:verification StrictInstanceFieldsTest + */ + +import java.lang.reflect.Field; +import jdk.internal.vm.annotation.Strict; + +public class StrictInstanceFieldsTest { + public static void main(String[] args) { + + // -------------- + // POSITIVE TESTS + // -------------- + + // Base case + Child c = new Child(); + System.out.println(c); + + // Constructor with control flow + ControlFlowChild c1 = new ControlFlowChild(true, true); + System.out.println(c1); + + // Constructor with try-catch-finally + TryCatchChild c2 = new TryCatchChild(); + System.out.println(c2); + + // Constructor with switch case + SwitchCaseChild c3 = new SwitchCaseChild(2); + System.out.println(c3); + + // Constructor with strict field assignment in conditional + AssignedInConditionalChild c4 = new AssignedInConditionalChild(); + System.out.println(c4); + + // Constructor with nested constructor calls + NestedConstructorChild c5 = new NestedConstructorChild(); + System.out.println(c5); + + // Final stirct fields defined in constructor + FinalChild fc = new FinalChild(); + System.out.println(fc); + + // -------------- + // NEGATIVE TESTS + // -------------- + + // Field not initialized before super call + try { + BadChild child = new BadChild(); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("All strict final fields must be initialized before super()")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Field not initialized before super call + try { + BadChild1 child = new BadChild1(); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("All strict final fields must be initialized before super()")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Constructor with control flow but field is not initialized + try { + ControlFlowChildBad child = new ControlFlowChildBad(true, false); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("Inconsistent stackmap frames at branch target")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Constructor with try-catch but field is not initialized + try { + TryCatchChildBad child = new TryCatchChildBad(); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("Inconsistent stackmap frames at branch target")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Early_Larval frame contains another early_larval instead of a base frame + try { + NestedEarlyLarval child = new NestedEarlyLarval(true, false); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("Early larval frame must be followed by a base frame")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Stack map table ends in early_larval frame without base frame + try { + EndsInEarlyLarval child = new EndsInEarlyLarval(true, false); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("Early larval frame must be followed by a base frame")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + // Early_larval frame includes a strict field not preset in the original set of unset fields + try { + StrictFieldsNotSubset child = new StrictFieldsNotSubset(true, false); + System.out.println(child); + throw new RuntimeException("Should fail verification"); + } catch (java.lang.VerifyError e) { + if (!e.getMessage().contains("Strict fields not a subset of initial strict instance fields")) { + throw new RuntimeException("wrong exception: " + e.getMessage()); + } + e.printStackTrace(); + } + + System.out.println("Passed"); + } +} + +class Parent { + int z; + + Parent() { + z = 0; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Field[] fields = this.getClass().getDeclaredFields(); + + for (Field f : fields) { + try { + sb.append(f.getName() + ": " + f.get(this) + "\n"); + } catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + return sb.toString(); + } +} + +class Child extends Parent { + + @Strict + int x; + @Strict + int y; + + Child() { + x = y = 1; + super(); + } +} + +class ControlFlowChild extends Parent { + + @Strict + int x; + @Strict + int y; + + ControlFlowChild(boolean a, boolean b) { + if (a) { + x = 1; + if (b) { + y = 1; + } else { + y = 2; + } + } else { + x = y = 3; + } + super(); + } +} + +class TryCatchChild extends Parent { + + @Strict + int x; + @Strict + int y; + + TryCatchChild() { + try { + x = 0; + int[] a = new int[1]; + System.out.println(a[2]); + } catch (java.lang.ArrayIndexOutOfBoundsException e) { + y = 0; + } finally { + x = y = 1; + } + super(); + } +} + +class AssignedInConditionalChild extends Parent { + + @Strict + final int x; + @Strict + final int y; + + AssignedInConditionalChild() { + if ((x=1) == 1) { + y = 1; + } else { + y = 2; + } + super(); + } +} + +class SwitchCaseChild extends Parent { + + @Strict + final int x; + @Strict + final int y; + + SwitchCaseChild(int n) { + switch(n) { + case 0: + x = y = 0; + break; + case 1: + x = y = 1; + break; + case 2: + x = y = 2; + break; + default: + x = y = 100; + break; + } + super(); + } +} + +class NestedConstructorChild extends Parent { + + @Strict + final int x; + @Strict + final int y; + + NestedConstructorChild(boolean a, boolean b) { + if (a) { + x = 1; + if (b) { + y = 1; + } else { + y = 2; + } + } else { + x = y = 3; + } + super(); + } + + NestedConstructorChild() { + this(true, true); + } +} + +class FinalChild extends Parent { + + @Strict + final int x; + @Strict + final int y; + + FinalChild() { + x = y = 1; + super(); + } +} diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/TryCatchChildBad.jasm b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/TryCatchChildBad.jasm new file mode 100644 index 00000000000..17adf3362f6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/TryCatchChildBad.jasm @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025, 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 TryCatchChild extends Parent { + @Strict int x; + @Strict int y; + + TryCatchChild() { + try { + x = 0; + int[] a = new int[1]; + System.out.println(a[2]); + } catch (java.lang.ArrayIndexOutOfBoundsException e) { + y = 0; + } + super(); + } +} +*/ + +identity class TryCatchChildBad extends Parent version 69:65535 +{ + @-jdk/internal/vm/annotation/Strict { } + strict Field x:I; + @-jdk/internal/vm/annotation/Strict { } + strict Field y:I; + + Method "":"()V" + stack 4 locals 2 + { + try T0, T1; + aload_0; + iconst_0; + putfield Field x:"I"; + iconst_1; + newarray int; + astore_1; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_1; + iconst_2; + iaload; + invokevirtual Method java/io/PrintStream.println:"(I)V"; + endtry T0,T1; + goto L63; + catch T0 java/lang/ArrayIndexOutOfBoundsException; + try T2; + stack_frame_type stack1; + stack_map class java/lang/ArrayIndexOutOfBoundsException; + astore_1; + aload_0; + iconst_0; + putfield Field y:"I"; + endtry T2; + goto L63; + catch T1 #0; + catch T2 #0; + stack_frame_type stack1; + stack_map class java/lang/Throwable; + astore_2; + aload_2; + athrow; + L63: stack_frame_type early_larval; + unset_fields; + frame_type same; + aload_0; + invokespecial Method Parent."":"()V"; + return; + } +} // end Class TryCatchChildBad