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   0x0020; // 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