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 /java/lang/invoke/common
 29  * @build test.java.lang.invoke.lib.InstructionHelper
 30  * @enablePreview
 31  * @run testng BootstrapMethodJumboArgsTest
 32  * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 BootstrapMethodJumboArgsTest
 33  */
 34 
 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 
 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         } else {
 57             return a;
 58         }
 59     }
 60 
 61     static Object bsmOne(MethodHandles.Lookup l, String name, Object type,
 62                          Object first, Object... args) {
 63         Object[] a = new Object[args.length + 1];
 64         a[0] = first;
 65         System.arraycopy(args, 0, a, 1, args.length);
 66         if (type instanceof MethodType) {
 67             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
 68         } else {
 69             return a;
 70         }
 71     }
 72 
 73     static Object bsmTwo(MethodHandles.Lookup l, String name, Object type,
 74                          Object first, Object second, Object... args) {
 75         Object[] a = new Object[args.length + 2];
 76         a[0] = first;
 77         a[1] = second;
 78         System.arraycopy(args, 0, a, 2, args.length);
 79         if (type instanceof MethodType) {
 80             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
 81         } else {
 82             return a;
 83         }
 84     }
 85 
 86     @Test
 87     public void testCondyWithJumboArgs() throws Throwable {
 88         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
 89 
 90         {
 91             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
 92                     L, "name", Object[].class,
 93                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class,
 94                             Object.class, Object[].class), expected);
 95 
 96             Object[] actual = (Object[]) mh.invoke();
 97             Assert.assertEquals(actual, expected);
 98         }
 99 
100         {
101             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
102                     L, "name", Object[].class,
103                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class,
104                             Object.class, Object.class, Object[].class), expected);
105 
106             Object[] actual = (Object[]) mh.invoke();
107             Assert.assertEquals(actual, expected);
108         }
109 
110         {
111             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
112                     L, "name", Object[].class,
113                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class,
114                             Object.class, Object.class, Object.class, Object[].class), expected);
115 
116             Object[] actual = (Object[]) mh.invoke();
117             Assert.assertEquals(actual, expected);
118         }
119     }
120 
121     @Test
122     public void testIndyWithJumboArgs() throws Throwable {
123         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
124 
125         {
126             MethodHandle mh = InstructionHelper.invokedynamic(
127                     L, "name", methodType(Object[].class),
128                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class,
129                             Object.class, Object[].class), expected);
130 
131             Object[] actual = (Object[]) mh.invoke();
132             Assert.assertEquals(actual, expected);
133         }
134 
135         {
136             MethodHandle mh = InstructionHelper.invokedynamic(
137                     L, "name", methodType(Object[].class),
138                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class,
139                             Object.class, Object.class, Object[].class), expected);
140 
141             Object[] actual = (Object[]) mh.invoke();
142             Assert.assertEquals(actual, expected);
143         }
144 
145         {
146             MethodHandle mh = InstructionHelper.invokedynamic(
147                     L, "name", methodType(Object[].class),
148                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class,
149                             Object.class, Object.class, Object.class, Object[].class), expected);
150 
151             Object[] actual = (Object[]) mh.invoke();
152             Assert.assertEquals(actual, expected);
153         }
154     }
155 }