1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25 Pseudo Java code:
  26 
  27 class CondyNestedResolution {
  28     public static Object bsm1arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4) {
  29         System.out.println("In bsm1arg");
  30         System.out.println(p4);
  31         return p4;
  32     }
  33     public static Object bsm2arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5) {
  34         System.out.println("In bsm2arg");
  35         System.out.println(p4);
  36         System.out.println(p5);
  37         return p4;
  38     }
  39     public static Object bsm3arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5, Object p6) {
  40         System.out.println("In bsm3arg");
  41         System.out.println(p4);
  42         System.out.println(p5);
  43         System.out.println(p6);
  44         return p4;
  45     }
  46     public static Object bsm4arg(MethodHandles$Lookup p1, String p2, Object p3, Object p4, Object p5, Object p6, Object p7) {
  47         System.out.println("In bsm4arg");
  48         System.out.println(p4);
  49         System.out.println(p5);
  50         System.out.println(p6);
  51         System.out.println(p7);
  52         return p4;
  53     }
  54 
  55     public static void test_condy() {
  56         // The following condy of BSM#8 results in the invocation of bootstrap method bsm4arg with the following
  57         // parameters:
  58         // bsm4arg(bsm1arg("hello1"),
  59         //         bsm1arg("hello2"),
  60         //         bsm3arg(bsm1arg("hello4"), bsm2arg(bsm1arg("hello6"), (circular reference to BSM#8)), bsm1arg("hello5")),
  61         //         bsm1arg("hello3"));
  62         // JVMS 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution
  63         // Ensure that calls to bsm1arg("hello5") and bsm1arg("hello3") are never resolved due to the nested condy circularity
  64         // which results in a StackOverflowError.
  65         //
  66         ldc Dynamic BSM#8;
  67     }
  68     public static void main(String args[]) {
  69         CondyNestedResolution.test_condy();
  70     }
  71 }
  72 
  73 BootstrapMethods:
  74   BSM0=invokestatic CondyNestedResolution.bsm1arg("hello1");
  75   BSM1=invokestatic CondyNestedResolution.bsm1arg("hello2");
  76   BSM2=invokestatic CondyNestedResolution.bsm1arg("hello4");
  77   BSM3=invokestatic CondyNestedResolution.bsm1arg("hello6");
  78   BSM4=invokestatic CondyNestedResolution.bsm2arg(BSM#3, BSM#8);
  79   BSM5=invokestatic CondyNestedResolution.bsm1arg("hello5");
  80   BSM6=invokestatic CondyNestedResolution.bsm3arg(BSM#2, BSM#4, BSM#5);
  81   BSM7=invokestatic CondyNestedResolution.bsm1arg("hello3");
  82   BSM8=invokestatic CondyNestedResolution.bsm4arg(BSM#0, BSM#1, BSM#6, BSM#7);
  83 
  84 Expected output:
  85   In bsm1arg
  86   hello1
  87   In bsm1arg
  88   hello2
  89   In bsm1arg
  90   hello4
  91   In bsm1arg
  92   hello6
  93   Exception in thread "main" java.lang.StackOverflowError
  94           at java.base/java.lang.invoke.MethodHandleNatives.copyOutBootstrapArguments(Native Method)
  95 */
  96 
  97 
  98 class CondyNestedResolution {
  99   0xCAFEBABE;
 100   0; // minor version
 101   55; // version
 102   [85] { // Constant Pool
 103     ; // first element is empty
 104     String #22; // #1     at 0x0A
 105     String #61; // #2     at 0x0D
 106     String #11; // #3     at 0x10
 107     Dynamic 8s #12; // #4     at 0x13
 108     Method #51 #10; // #5     at 0x18
 109     Method #13 #39; // #6     at 0x1D
 110     Field #50 #81; // #7     at 0x22
 111     Method #84 #45; // #8     at 0x27
 112     Utf8 "java/io/PrintStream"; // #9     at 0x2C
 113     NameAndType #71 #47; // #10     at 0x42
 114     Utf8 "In bsm1arg"; // #11     at 0x47
 115     NameAndType #18 #17; // #12     at 0x54
 116     class #9; // #13     at 0x59
 117     Utf8 "SourceFile"; // #14     at 0x5C
 118     Utf8 "bsm3arg"; // #15     at 0x69
 119     Utf8 "CondyNestedResolution.jasm"; // #16     at 0x73
 120     Utf8 "Ljava/lang/String;"; // #17     at 0x90
 121     Utf8 "name"; // #18     at 0xA5
 122     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
 123     Utf8 "test_condy"; // #20     at 0x0144
 124     NameAndType #15 #19; // #21     at 0x0151
 125     Utf8 "In bsm2arg"; // #22     at 0x0156
 126     Utf8 "Code"; // #23     at 0x0163
 127     Utf8 "([Ljava/lang/String;)V"; // #24     at 0x016A
 128     Utf8 "bsm4arg"; // #25     at 0x0183
 129     Utf8 "out"; // #26     at 0x018D
 130     NameAndType #69 #55; // #27     at 0x0193
 131     Utf8 "BootstrapMethods"; // #28     at 0x0198
 132     MethodHandle 6b #44; // #29     at 0x01AB
 133     Method #84 #63; // #30     at 0x01AF
 134     Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #31     at 0x01B4
 135     Method #84 #27; // #32     at 0x0228
 136     MethodHandle 6b #30; // #33     at 0x022D
 137     MethodHandle 6b #30; // #34     at 0x0231
 138     MethodHandle 6b #30; // #35     at 0x0235
 139     MethodHandle 6b #30; // #36     at 0x0239
 140     MethodHandle 6b #30; // #37     at 0x023D
 141     MethodHandle 6b #30; // #38     at 0x0241
 142     NameAndType #40 #41; // #39     at 0x0245
 143     Utf8 "println"; // #40     at 0x024A
 144     Utf8 "(Ljava/lang/Object;)V"; // #41     at 0x0254
 145     Utf8 "java/lang/Object"; // #42     at 0x026C
 146     Utf8 "java/lang/System"; // #43     at 0x027F
 147     Method #84 #21; // #44     at 0x0292
 148     NameAndType #20 #47; // #45     at 0x0297
 149     MethodHandle 6b #82; // #46     at 0x029C
 150     Utf8 "()V"; // #47     at 0x02A0
 151     String #62; // #48     at 0x02A6
 152     String #64; // #49     at 0x02A9
 153     class #43; // #50     at 0x02AC
 154     class #42; // #51     at 0x02AF
 155     String #65; // #52     at 0x02B2
 156     String #66; // #53     at 0x02B5
 157     String #67; // #54     at 0x02B8
 158     Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"; // #55     at 0x02BB
 159     Utf8 "main"; // #56     at 0x0341
 160     String #68; // #57     at 0x0348
 161     MethodHandle 6b #32; // #58     at 0x034B
 162     Utf8 "bsm1arg"; // #59     at 0x034F
 163     NameAndType #25 #83; // #60     at 0x0359
 164     Utf8 "In bsm4arg"; // #61     at 0x035E
 165     Utf8 "hello6"; // #62     at 0x036B
 166     NameAndType #59 #31; // #63     at 0x0374
 167     Utf8 "hello5"; // #64     at 0x0379
 168     Utf8 "hello4"; // #65     at 0x0382
 169     Utf8 "hello3"; // #66     at 0x038B
 170     Utf8 "hello2"; // #67     at 0x0394
 171     Utf8 "hello1"; // #68     at 0x039D
 172     Utf8 "bsm2arg"; // #69     at 0x03A6
 173     Utf8 "Ljava/io/PrintStream;"; // #70     at 0x03B0
 174     Utf8 "<init>"; // #71     at 0x03C8
 175     Utf8 "CondyNestedResolution"; // #72     at 0x03D1
 176     Dynamic 7s #12; // #73     at 0x03E9
 177     Dynamic 6s #12; // #74     at 0x03EE
 178     Dynamic 5s #12; // #75     at 0x03F3
 179     Dynamic 4s #12; // #76     at 0x03F8
 180     Dynamic 3s #12; // #77     at 0x03FD
 181     Dynamic 0s #12; // #78     at 0x0402
 182     Dynamic 1s #12; // #79     at 0x0407
 183     Dynamic 2s #12; // #80     at 0x040C
 184     NameAndType #26 #70; // #81     at 0x0411
 185     Method #84 #60; // #82     at 0x0416
 186     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
 187     class #72; // #84     at 0x04C5
 188   } // Constant Pool
 189 
 190   0x0000; // access [ ]
 191   #84;// this_cpx
 192   #51;// super_cpx
 193 
 194   [0] { // Interfaces
 195   } // Interfaces
 196 
 197   [0] { // fields
 198   } // fields
 199 
 200   [7] { // methods
 201     { // Member at 0x04D4
 202       0x0001; // access
 203       #71; // name_cpx
 204       #47; // sig_cpx
 205       [1] { // Attributes
 206         Attr(#23, 17) { // Code at 0x04DC
 207           1; // max_stack
 208           1; // max_locals
 209           Bytes[5]{
 210             0x2AB70005B1;
 211           }
 212           [0] { // Traps
 213           } // end Traps
 214           [0] { // Attributes
 215           } // Attributes
 216         } // end Code
 217       } // Attributes
 218     } // Member
 219     ;
 220     { // Member at 0x04F3
 221       0x0009; // access
 222       #59; // name_cpx
 223       #31; // sig_cpx
 224       [1] { // Attributes
 225         Attr(#23, 29) { // Code at 0x04FB
 226           4; // max_stack
 227           4; // max_locals
 228           Bytes[17]{
 229             0xB200071203B60006;
 230             0xB200072DB600062D;
 231             0xB0;
 232           }
 233           [0] { // Traps
 234           } // end Traps
 235           [0] { // Attributes
 236           } // Attributes
 237         } // end Code
 238       } // Attributes
 239     } // Member
 240     ;
 241     { // Member at 0x051E
 242       0x0009; // access
 243       #69; // name_cpx
 244       #55; // sig_cpx
 245       [1] { // Attributes
 246         Attr(#23, 37) { // Code at 0x0526
 247           8; // max_stack
 248           8; // max_locals
 249           Bytes[25]{
 250             0xB200071201B60006;
 251             0xB200072DB60006B2;
 252             0x00071904B600062D;
 253             0xB0;
 254           }
 255           [0] { // Traps
 256           } // end Traps
 257           [0] { // Attributes
 258           } // Attributes
 259         } // end Code
 260       } // Attributes
 261     } // Member
 262     ;
 263     { // Member at 0x0551
 264       0x0009; // access
 265       #15; // name_cpx
 266       #19; // sig_cpx
 267       [1] { // Attributes
 268         Attr(#23, 45) { // Code at 0x0559
 269           19; // max_stack
 270           19; // max_locals
 271           Bytes[33]{
 272             0xB200071202B60006;
 273             0xB200072DB60006B2;
 274             0x00071904B60006B2;
 275             0x00071905B600062D;
 276             0xB0;
 277           }
 278           [0] { // Traps
 279           } // end Traps
 280           [0] { // Attributes
 281           } // Attributes
 282         } // end Code
 283       } // Attributes
 284     } // Member
 285     ;
 286     { // Member at 0x058C
 287       0x0009; // access
 288       #25; // name_cpx
 289       #83; // sig_cpx
 290       [1] { // Attributes
 291         Attr(#23, 53) { // Code at 0x0594
 292           19; // max_stack
 293           19; // max_locals
 294           Bytes[41]{
 295             0xB200071202B60006;
 296             0xB200072DB60006B2;
 297             0x00071904B60006B2;
 298             0x00071905B60006B2;
 299             0x00071906B600062D;
 300             0xB0;
 301           }
 302           [0] { // Traps
 303           } // end Traps
 304           [0] { // Attributes
 305           } // Attributes
 306         } // end Code
 307       } // Attributes
 308     } // Member
 309     ;
 310     { // Member at 0x05CF
 311       0x0009; // access
 312       #20; // name_cpx
 313       #47; // sig_cpx
 314       [1] { // Attributes
 315         Attr(#23, 15) { // Code at 0x05D7
 316           12; // max_stack
 317           12; // max_locals
 318           Bytes[3]{
 319             0x1204B1;
 320           }
 321           [0] { // Traps
 322           } // end Traps
 323           [0] { // Attributes
 324           } // Attributes
 325         } // end Code
 326       } // Attributes
 327     } // Member
 328     ;
 329     { // Member at 0x05EC
 330       0x0009; // access
 331       #56; // name_cpx
 332       #24; // sig_cpx
 333       [1] { // Attributes
 334         Attr(#23, 16) { // Code at 0x05F4
 335           2; // max_stack
 336           2; // max_locals
 337           Bytes[4]{
 338             0xB80008B1;
 339           }
 340           [0] { // Traps
 341           } // end Traps
 342           [0] { // Attributes
 343           } // Attributes
 344         } // end Code
 345       } // Attributes
 346     } // Member
 347   } // methods
 348 
 349   [2] { // Attributes
 350     Attr(#14, 2) { // SourceFile at 0x060C
 351       #16;
 352     } // end SourceFile
 353     ;
 354     Attr(#28, 68) { // BootstrapMethods at 0x0614
 355       [9] { // bootstrap_methods
 356         {  //  bootstrap_method
 357           #36; // bootstrap_method_ref
 358           [1] { // bootstrap_arguments
 359             #57; //  at 0x0622
 360           }  //  bootstrap_arguments
 361         }  //  bootstrap_method
 362         ;
 363         {  //  bootstrap_method
 364           #37; // bootstrap_method_ref
 365           [1] { // bootstrap_arguments
 366             #54; //  at 0x0628
 367           }  //  bootstrap_arguments
 368         }  //  bootstrap_method
 369         ;
 370         {  //  bootstrap_method
 371           #38; // bootstrap_method_ref
 372           [1] { // bootstrap_arguments
 373             #52; //  at 0x062E
 374           }  //  bootstrap_arguments
 375         }  //  bootstrap_method
 376         ;
 377         {  //  bootstrap_method
 378           #35; // bootstrap_method_ref
 379           [1] { // bootstrap_arguments
 380             #48; //  at 0x0634
 381           }  //  bootstrap_arguments
 382         }  //  bootstrap_method
 383         ;
 384         {  //  bootstrap_method
 385           #58; // bootstrap_method_ref
 386           [2] { // bootstrap_arguments
 387             #77; //  at 0x063A
 388             #4; //  at 0x063C
 389           }  //  bootstrap_arguments
 390         }  //  bootstrap_method
 391         ;
 392         {  //  bootstrap_method
 393           #34; // bootstrap_method_ref
 394           [1] { // bootstrap_arguments
 395             #49; //  at 0x0642
 396           }  //  bootstrap_arguments
 397         }  //  bootstrap_method
 398         ;
 399         {  //  bootstrap_method
 400           #29; // bootstrap_method_ref
 401           [3] { // bootstrap_arguments
 402             #80; //  at 0x0648
 403             #76; //  at 0x064A
 404             #75; //  at 0x064C
 405           }  //  bootstrap_arguments
 406         }  //  bootstrap_method
 407         ;
 408         {  //  bootstrap_method
 409           #33; // bootstrap_method_ref
 410           [1] { // bootstrap_arguments
 411             #53; //  at 0x0652
 412           }  //  bootstrap_arguments
 413         }  //  bootstrap_method
 414         ;
 415         {  //  bootstrap_method
 416           #46; // bootstrap_method_ref
 417           [4] { // bootstrap_arguments
 418             #78; //  at 0x0658
 419             #79; //  at 0x065A
 420             #74; //  at 0x065C
 421             #73; //  at 0x065E
 422           }  //  bootstrap_arguments
 423         }  //  bootstrap_method
 424       }
 425     } // end BootstrapMethods
 426   } // Attributes
 427 } // end class CondyNestedResolution