1 /*
2  * Copyright (c) 2017, 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  * @test
26  * @bug 8186046
27  * @summary Test bootstrap methods throwing an exception
28  * @library /lib/testlibrary/bytecode /java/lang/invoke/common
29  * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
30  * @run testng BootstrapMethodJumboArgsTest
31  * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 BootstrapMethodJumboArgsTest
32  */
33 
34 import jdk.experimental.bytecode.PoolHelper;
35 import org.testng.Assert;
36 import org.testng.annotations.Test;
37 import test.java.lang.invoke.lib.InstructionHelper;
38 
39 import java.lang.invoke.ConstantCallSite;
40 import java.lang.invoke.MethodHandle;
41 import java.lang.invoke.MethodHandles;
42 import java.lang.invoke.MethodType;
43 import java.util.stream.IntStream;
44 
45 import static java.lang.invoke.MethodType.methodType;
46 
47 public class BootstrapMethodJumboArgsTest {
48     static final MethodHandles.Lookup L = MethodHandles.lookup();
49 
50 
bsmZero(MethodHandles.Lookup l, String name, Object type, Object... args)51     static Object bsmZero(MethodHandles.Lookup l, String name, Object type,
52                       Object... args) {
53         Object[] a = args.clone();
54         if (type instanceof MethodType) {
55             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
56         }
57         else {
58             return a;
59         }
60     }
61 
bsmOne(MethodHandles.Lookup l, String name, Object type, Object first, Object... args)62     static Object bsmOne(MethodHandles.Lookup l, String name, Object type,
63                          Object first, Object... args) {
64         Object[] a = new Object[args.length + 1];
65         a[0] = first;
66         System.arraycopy(args, 0, a, 1, args.length);
67         if (type instanceof MethodType) {
68             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
69         }
70         else {
71             return a;
72         }
73     }
74 
bsmTwo(MethodHandles.Lookup l, String name, Object type, Object first, Object second, Object... args)75     static Object bsmTwo(MethodHandles.Lookup l, String name, Object type,
76                          Object first, Object second, Object... args) {
77         Object[] a = new Object[args.length + 2];
78         a[0] = first;
79         a[1] = second;
80         System.arraycopy(args, 0, a, 2, args.length);
81         if (type instanceof MethodType) {
82             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
83         }
84         else {
85             return a;
86         }
87     }
88 
manyStaticStrings(String[] args, PoolHelper.StaticArgListBuilder<String, String, byte[]> staticArgs)89     static void manyStaticStrings(String[] args, PoolHelper.StaticArgListBuilder<String, String, byte[]> staticArgs) {
90         for (String s : args) {
91             staticArgs.add(s);
92         }
93     }
94 
95     @Test
testCondyWithJumboArgs()96     public void testCondyWithJumboArgs() throws Throwable {
97         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
98 
99         {
100             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
101                     L, "name", Object[].class,
102                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object[].class),
103                     S -> manyStaticStrings(expected, S));
104 
105             Object[] actual = (Object[]) mh.invoke();
106             Assert.assertEquals(actual, expected);
107         }
108 
109         {
110             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
111                     L, "name", Object[].class,
112                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object[].class),
113                     S -> manyStaticStrings(expected, S));
114 
115             Object[] actual = (Object[]) mh.invoke();
116             Assert.assertEquals(actual, expected);
117         }
118 
119         {
120             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
121                     L, "name", Object[].class,
122                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object.class, Object[].class),
123                     S -> manyStaticStrings(expected, S));
124 
125             Object[] actual = (Object[]) mh.invoke();
126             Assert.assertEquals(actual, expected);
127         }
128     }
129 
130     @Test
testIndyWithJumboArgs()131     public void testIndyWithJumboArgs() throws Throwable {
132         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
133 
134         {
135             MethodHandle mh = InstructionHelper.invokedynamic(
136                     L, "name", methodType(Object[].class),
137                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object[].class),
138                     S -> manyStaticStrings(expected, S));
139 
140             Object[] actual = (Object[]) mh.invoke();
141             Assert.assertEquals(actual, expected);
142         }
143 
144         {
145             MethodHandle mh = InstructionHelper.invokedynamic(
146                     L, "name", methodType(Object[].class),
147                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object[].class),
148                     S -> manyStaticStrings(expected, S));
149 
150             Object[] actual = (Object[]) mh.invoke();
151             Assert.assertEquals(actual, expected);
152         }
153 
154         {
155             MethodHandle mh = InstructionHelper.invokedynamic(
156                     L, "name", methodType(Object[].class),
157                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class, Object.class, Object.class, Object.class, Object[].class),
158                     S -> manyStaticStrings(expected, S));
159 
160             Object[] actual = (Object[]) mh.invoke();
161             Assert.assertEquals(actual, expected);
162         }
163     }
164 }
165