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  * @enablePreview
 30  * @run testng BootstrapMethodJumboArgsTest
 31  * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 BootstrapMethodJumboArgsTest
 32  */
 33 
 34 import org.testng.Assert;
 35 import org.testng.annotations.Test;
 36 import test.java.lang.invoke.lib.InstructionHelper;
 37 
 38 import java.lang.invoke.ConstantCallSite;
 39 import java.lang.invoke.MethodHandle;
 40 import java.lang.invoke.MethodHandles;
 41 import java.lang.invoke.MethodType;
 42 import java.util.stream.IntStream;
 43 
 44 import static java.lang.invoke.MethodType.methodType;
 45 
 46 public class BootstrapMethodJumboArgsTest {
 47     static final MethodHandles.Lookup L = MethodHandles.lookup();
 48 
 49 
 50     static Object bsmZero(MethodHandles.Lookup l, String name, Object type,
 51                           Object... args) {
 52         Object[] a = args.clone();
 53         if (type instanceof MethodType) {
 54             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
 55         } else {
 56             return a;
 57         }
 58     }
 59 
 60     static Object bsmOne(MethodHandles.Lookup l, String name, Object type,
 61                          Object first, Object... args) {
 62         Object[] a = new Object[args.length + 1];
 63         a[0] = first;
 64         System.arraycopy(args, 0, a, 1, args.length);
 65         if (type instanceof MethodType) {
 66             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
 67         } else {
 68             return a;
 69         }
 70     }
 71 
 72     static Object bsmTwo(MethodHandles.Lookup l, String name, Object type,
 73                          Object first, Object second, Object... args) {
 74         Object[] a = new Object[args.length + 2];
 75         a[0] = first;
 76         a[1] = second;
 77         System.arraycopy(args, 0, a, 2, args.length);
 78         if (type instanceof MethodType) {
 79             return new ConstantCallSite(MethodHandles.constant(Object[].class, a));
 80         } else {
 81             return a;
 82         }
 83     }
 84 
 85     @Test
 86     public void testCondyWithJumboArgs() throws Throwable {
 87         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
 88 
 89         {
 90             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
 91                     L, "name", Object[].class,
 92                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class,
 93                             Object.class, Object[].class), expected);
 94 
 95             Object[] actual = (Object[]) mh.invoke();
 96             Assert.assertEquals(actual, expected);
 97         }
 98 
 99         {
100             MethodHandle mh = InstructionHelper.ldcDynamicConstant(
101                     L, "name", Object[].class,
102                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class,
103                             Object.class, Object.class, Object[].class), expected);
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                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class,
113                             Object.class, Object.class, Object.class, Object[].class), expected);
114 
115             Object[] actual = (Object[]) mh.invoke();
116             Assert.assertEquals(actual, expected);
117         }
118     }
119 
120     @Test
121     public void testIndyWithJumboArgs() throws Throwable {
122         String[] expected = IntStream.range(0, 1000).mapToObj(Integer::toString).toArray(String[]::new);
123 
124         {
125             MethodHandle mh = InstructionHelper.invokedynamic(
126                     L, "name", methodType(Object[].class),
127                     "bsmZero", methodType(Object.class, MethodHandles.Lookup.class, String.class,
128                             Object.class, Object[].class), expected);
129 
130             Object[] actual = (Object[]) mh.invoke();
131             Assert.assertEquals(actual, expected);
132         }
133 
134         {
135             MethodHandle mh = InstructionHelper.invokedynamic(
136                     L, "name", methodType(Object[].class),
137                     "bsmOne", methodType(Object.class, MethodHandles.Lookup.class, String.class,
138                             Object.class, Object.class, Object[].class), expected);
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                     "bsmTwo", methodType(Object.class, MethodHandles.Lookup.class, String.class,
148                             Object.class, Object.class, Object.class, Object[].class), expected);
149 
150             Object[] actual = (Object[]) mh.invoke();
151             Assert.assertEquals(actual, expected);
152         }
153     }
154 }