8203435: Circular nested dynamic constant test needed to confirm JVMS resolution behavior
Summary: Additional of circular nested dynamic constant test.
Reviewed-by: acorn, psandoz
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/condy/CondyNestedResolution.jcod Mon Jun 04 11:32:00 2018 -0400
@@ -0,0 +1,427 @@
+/*
+ * 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.
+ */
+
+/*
+Pseudo Java code:
+
+class CondyNestedResolution {
+ public static Object bsm1arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4) {
+ System.out.println("In bsm1arg");
+ System.out.println(p4);
+ return p4;
+ }
+ public static Object bsm2arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5) {
+ System.out.println("In bsm2arg");
+ System.out.println(p4);
+ System.out.println(p5);
+ return p4;
+ }
+ public static Object bsm3arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5, Object p6) {
+ System.out.println("In bsm3arg");
+ System.out.println(p4);
+ System.out.println(p5);
+ System.out.println(p6);
+ return p4;
+ }
+ public static Object bsm4arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5, Object p6, Object p7) {
+ System.out.println("In bsm4arg");
+ System.out.println(p4);
+ System.out.println(p5);
+ System.out.println(p6);
+ System.out.println(p7);
+ return p4;
+ }
+
+ public static void test_condy() {
+ // The following condy of BSM#8 results in the invocation of bootstrap method bsm4arg with the following
+ // parameters:
+ // bsm4arg(bsm1arg("hello1"),
+ // bsm1arg("hello2"),
+ // bsm3arg(bsm1arg("hello4"), bsm2arg(bsm1arg("hello6"), (circular reference to BSM#8)), bsm1arg("hello5")),
+ // bsm1arg("hello3"));
+ // JVMS 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution
+ // Ensure that calls to bsm1arg("hello5") and bsm1arg("hello3") are never resolved due to the nested condy circularity
+ // which results in a StackOverflowError.
+ //
+ ldc Dynamic BSM#8;
+ }
+ public static void main(String args[]) {
+ CondyNestedResolution.test_condy();
+ }
+}
+
+BootstrapMethods:
+ BSM0=invokestatic CondyNestedResolution.bsm1arg("hello1");
+ BSM1=invokestatic CondyNestedResolution.bsm1arg("hello2");
+ BSM2=invokestatic CondyNestedResolution.bsm1arg("hello4");
+ BSM3=invokestatic CondyNestedResolution.bsm1arg("hello6");
+ BSM4=invokestatic CondyNestedResolution.bsm2arg(BSM#3, BSM#8);
+ BSM5=invokestatic CondyNestedResolution.bsm1arg("hello5");
+ BSM6=invokestatic CondyNestedResolution.bsm3arg(BSM#2, BSM#4, BSM#5);
+ BSM7=invokestatic CondyNestedResolution.bsm1arg("hello3");
+ BSM8=invokestatic CondyNestedResolution.bsm4arg(BSM#0, BSM#1, BSM#6, BSM#7);
+
+Expected output:
+ In bsm1arg
+ hello1
+ In bsm1arg
+ hello2
+ In bsm1arg
+ hello4
+ In bsm1arg
+ hello6
+ Exception in thread "main" java.lang.StackOverflowError
+ at java.base/java.lang.invoke.MethodHandleNatives.copyOutBootstrapArguments(Native Method)
+*/
+
+
+class CondyNestedResolution {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [85] { // Constant Pool
+ ; // first element is empty
+ String #22; // #1 at 0x0A
+ String #61; // #2 at 0x0D
+ String #11; // #3 at 0x10
+ Dynamic 8s #12; // #4 at 0x13
+ Method #51 #10; // #5 at 0x18
+ Method #13 #39; // #6 at 0x1D
+ Field #50 #81; // #7 at 0x22
+ Method #84 #45; // #8 at 0x27
+ Utf8 "java/io/PrintStream"; // #9 at 0x2C
+ NameAndType #71 #47; // #10 at 0x42
+ Utf8 "In bsm1arg"; // #11 at 0x47
+ NameAndType #18 #17; // #12 at 0x54
+ class #9; // #13 at 0x59
+ Utf8 "SourceFile"; // #14 at 0x5C
+ Utf8 "bsm3arg"; // #15 at 0x69
+ Utf8 "CondyNestedResolution.jasm"; // #16 at 0x73
+ Utf8 "Ljava/lang/String;"; // #17 at 0x90
+ Utf8 "name"; // #18 at 0xA5
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #19 at 0xAC
+ Utf8 "test_condy"; // #20 at 0x0144
+ NameAndType #15 #19; // #21 at 0x0151
+ Utf8 "In bsm2arg"; // #22 at 0x0156
+ Utf8 "Code"; // #23 at 0x0163
+ Utf8 "([Ljava/lang/String;)V"; // #24 at 0x016A
+ Utf8 "bsm4arg"; // #25 at 0x0183
+ Utf8 "out"; // #26 at 0x018D
+ NameAndType #69 #55; // #27 at 0x0193
+ Utf8 "BootstrapMethods"; // #28 at 0x0198
+ MethodHandle 6b #44; // #29 at 0x01AB
+ Method #84 #63; // #30 at 0x01AF
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #31 at 0x01B4
+ Method #84 #27; // #32 at 0x0228
+ MethodHandle 6b #30; // #33 at 0x022D
+ MethodHandle 6b #30; // #34 at 0x0231
+ MethodHandle 6b #30; // #35 at 0x0235
+ MethodHandle 6b #30; // #36 at 0x0239
+ MethodHandle 6b #30; // #37 at 0x023D
+ MethodHandle 6b #30; // #38 at 0x0241
+ NameAndType #40 #41; // #39 at 0x0245
+ Utf8 "println"; // #40 at 0x024A
+ Utf8 "(Ljava/lang/Object;)V"; // #41 at 0x0254
+ Utf8 "java/lang/Object"; // #42 at 0x026C
+ Utf8 "java/lang/System"; // #43 at 0x027F
+ Method #84 #21; // #44 at 0x0292
+ NameAndType #20 #47; // #45 at 0x0297
+ MethodHandle 6b #82; // #46 at 0x029C
+ Utf8 "()V"; // #47 at 0x02A0
+ String #62; // #48 at 0x02A6
+ String #64; // #49 at 0x02A9
+ class #43; // #50 at 0x02AC
+ class #42; // #51 at 0x02AF
+ String #65; // #52 at 0x02B2
+ String #66; // #53 at 0x02B5
+ String #67; // #54 at 0x02B8
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #55 at 0x02BB
+ Utf8 "main"; // #56 at 0x0341
+ String #68; // #57 at 0x0348
+ MethodHandle 6b #32; // #58 at 0x034B
+ Utf8 "bsm1arg"; // #59 at 0x034F
+ NameAndType #25 #83; // #60 at 0x0359
+ Utf8 "In bsm4arg"; // #61 at 0x035E
+ Utf8 "hello6"; // #62 at 0x036B
+ NameAndType #59 #31; // #63 at 0x0374
+ Utf8 "hello5"; // #64 at 0x0379
+ Utf8 "hello4"; // #65 at 0x0382
+ Utf8 "hello3"; // #66 at 0x038B
+ Utf8 "hello2"; // #67 at 0x0394
+ Utf8 "hello1"; // #68 at 0x039D
+ Utf8 "bsm2arg"; // #69 at 0x03A6
+ Utf8 "Ljava/io/PrintStream;"; // #70 at 0x03B0
+ Utf8 "<init>"; // #71 at 0x03C8
+ Utf8 "CondyNestedResolution"; // #72 at 0x03D1
+ Dynamic 7s #12; // #73 at 0x03E9
+ Dynamic 6s #12; // #74 at 0x03EE
+ Dynamic 5s #12; // #75 at 0x03F3
+ Dynamic 4s #12; // #76 at 0x03F8
+ Dynamic 3s #12; // #77 at 0x03FD
+ Dynamic 0s #12; // #78 at 0x0402
+ Dynamic 1s #12; // #79 at 0x0407
+ Dynamic 2s #12; // #80 at 0x040C
+ NameAndType #26 #70; // #81 at 0x0411
+ Method #84 #60; // #82 at 0x0416
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #83 at 0x041B
+ class #72; // #84 at 0x04C5
+ } // Constant Pool
+
+ 0x0000; // access [ ]
+ #84;// this_cpx
+ #51;// super_cpx
+
+ [0] { // Interfaces
+ } // Interfaces
+
+ [0] { // fields
+ } // fields
+
+ [7] { // methods
+ { // Member at 0x04D4
+ 0x0001; // access
+ #71; // name_cpx
+ #47; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 17) { // Code at 0x04DC
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[5]{
+ 0x2AB70005B1;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x04F3
+ 0x0009; // access
+ #59; // name_cpx
+ #31; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 29) { // Code at 0x04FB
+ 4; // max_stack
+ 4; // max_locals
+ Bytes[17]{
+ 0xB200071203B60006;
+ 0xB200072DB600062D;
+ 0xB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x051E
+ 0x0009; // access
+ #69; // name_cpx
+ #55; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 37) { // Code at 0x0526
+ 8; // max_stack
+ 8; // max_locals
+ Bytes[25]{
+ 0xB200071201B60006;
+ 0xB200072DB60006B2;
+ 0x00071904B600062D;
+ 0xB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x0551
+ 0x0009; // access
+ #15; // name_cpx
+ #19; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 45) { // Code at 0x0559
+ 19; // max_stack
+ 19; // max_locals
+ Bytes[33]{
+ 0xB200071202B60006;
+ 0xB200072DB60006B2;
+ 0x00071904B60006B2;
+ 0x00071905B600062D;
+ 0xB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x058C
+ 0x0009; // access
+ #25; // name_cpx
+ #83; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 53) { // Code at 0x0594
+ 19; // max_stack
+ 19; // max_locals
+ Bytes[41]{
+ 0xB200071202B60006;
+ 0xB200072DB60006B2;
+ 0x00071904B60006B2;
+ 0x00071905B60006B2;
+ 0x00071906B600062D;
+ 0xB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x05CF
+ 0x0009; // access
+ #20; // name_cpx
+ #47; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 15) { // Code at 0x05D7
+ 12; // max_stack
+ 12; // max_locals
+ Bytes[3]{
+ 0x1204B1;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x05EC
+ 0x0009; // access
+ #56; // name_cpx
+ #24; // sig_cpx
+ [1] { // Attributes
+ Attr(#23, 16) { // Code at 0x05F4
+ 2; // max_stack
+ 2; // max_locals
+ Bytes[4]{
+ 0xB80008B1;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [2] { // Attributes
+ Attr(#14, 2) { // SourceFile at 0x060C
+ #16;
+ } // end SourceFile
+ ;
+ Attr(#28, 68) { // BootstrapMethods at 0x0614
+ [9] { // bootstrap_methods
+ { // bootstrap_method
+ #36; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #57; // at 0x0622
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #37; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #54; // at 0x0628
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #38; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #52; // at 0x062E
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #35; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #48; // at 0x0634
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #58; // bootstrap_method_ref
+ [2] { // bootstrap_arguments
+ #77; // at 0x063A
+ #4; // at 0x063C
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #34; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #49; // at 0x0642
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #29; // bootstrap_method_ref
+ [3] { // bootstrap_arguments
+ #80; // at 0x0648
+ #76; // at 0x064A
+ #75; // at 0x064C
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #33; // bootstrap_method_ref
+ [1] { // bootstrap_arguments
+ #53; // at 0x0652
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #46; // bootstrap_method_ref
+ [4] { // bootstrap_arguments
+ #78; // at 0x0658
+ #79; // at 0x065A
+ #74; // at 0x065C
+ #73; // at 0x065E
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyNestedResolution
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/condy/CondyNestedResolutionTest.java Mon Jun 04 11:32:00 2018 -0400
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8203435
+ * @summary Test JVMs 5.4.3.6 with respect to a dynamically-computed constant and circularity.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile CondyNestedResolution.jcod
+ * @run main/othervm CondyNestedResolutionTest
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+/*
+ * JVMs section 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution
+ * "Let X be the symbolic reference currently being resolved, and let Y be a static argument of X
+ * to be resolved as described above. If X and Y are both dynamically-computed constants, and if Y
+ * is either the same as X or has a static argument that references X through its static arguments,
+ * directly or indirectly, resolution fails with a StackOverflowError.
+ */
+public class CondyNestedResolutionTest {
+ public static void main(String args[]) throws Throwable {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("CondyNestedResolution");
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("StackOverflowError");
+ oa.shouldContain("bsm1arg");
+ oa.shouldContain("hello1");
+ oa.shouldContain("hello2");
+ oa.shouldContain("hello4");
+ oa.shouldContain("hello6");
+ oa.shouldNotContain("hello3");
+ oa.shouldNotContain("hello5");
+ oa.shouldNotContain("bsm2arg");
+ oa.shouldNotContain("bsm3arg");
+ oa.shouldNotContain("bsm4arg");
+ oa.shouldHaveExitValue(1);
+ }
+}