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 arguments for condy 28 * @library /lib/testlibrary/bytecode /java/lang/invoke/common 29 * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper 30 * @run testng CondyStaticArgumentsTest 31 */ 32 33 import jdk.experimental.bytecode.PoolHelper; 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.MethodHandleInfo; 41 import java.lang.invoke.MethodHandles; 42 import java.lang.invoke.MethodType; 43 import java.lang.reflect.Method; 44 import java.math.BigDecimal; 45 import java.math.MathContext; 46 import java.util.StringJoiner; 47 import java.util.stream.Stream; 48 49 import static java.lang.invoke.MethodType.methodType; 50 51 public class CondyStaticArgumentsTest { 52 static final MethodHandles.Lookup L = MethodHandles.lookup(); 53 54 static class BSMInfo { 55 final String methodName; 56 final MethodHandle handle; 57 final String descriptor; 58 59 BSMInfo(String name) { 60 methodName = name; 61 62 Method m = Stream.of(CondyStaticArgumentsTest.class.getDeclaredMethods()) 63 .filter(x -> x.getName().equals(methodName)).findFirst() 64 .get(); 65 try { 66 handle = MethodHandles.lookup().unreflect(m); 67 } 68 catch (Exception e) { 69 throw new Error(e); 70 } 71 descriptor = handle.type().toMethodDescriptorString(); 72 } 73 74 static BSMInfo of(String name) { 75 return new BSMInfo(name); 76 } 77 } 78 79 static String basicArgs(MethodHandles.Lookup l, String name, Class<?> type, 80 int i, long j, float f, double d, 81 Class<?> c, String s, 82 MethodType mt, MethodHandle mh) { 83 return new StringJoiner("-") 84 .add(name) 85 .add(type.getSimpleName()) 86 .add(Integer.toString(i)) 87 .add(Long.toString(j)) 88 .add(Float.toString(f)) 89 .add(Double.toString(d)) 90 .add(c.getSimpleName()) 91 .add(s) 92 .add(mt.toString()) 93 .add(Integer.toString(mh.type().parameterCount())) 94 .toString(); 95 } 96 97 @Test 98 public void testBasicArgs() throws Throwable { 99 BSMInfo bi = BSMInfo.of("basicArgs"); 100 MethodHandleInfo mhi = MethodHandles.lookup().revealDirect(bi.handle); 101 102 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 103 L, "constant-name", String.class, 104 bi.methodName, bi.handle.type(), 105 S -> S.add(1).add(2L).add(3.0f).add(4.0d) 106 .add("java/lang/Number", PoolHelper::putClass) 107 .add("something", PoolHelper::putString) 108 .add("(IJFD)V", PoolHelper::putMethodType) 109 .add(mhi, (P, Z) -> { 110 return P.putHandle(mhi.getReferenceKind(), "CondyStaticArgumentsTest", mhi.getName(), bi.descriptor); 111 })); 112 113 Assert.assertEquals(mh.invoke(), "constant-name-String-1-2-3.0-4.0-Number-something-(int,long,float,double)void-11"); 114 } 115 116 117 static MathContext mathContext(MethodHandles.Lookup l, String value, Class<?> type) { 118 switch (value) { 119 case "UNLIMITED": 120 return MathContext.UNLIMITED; 121 case "DECIMAL32": 122 return MathContext.DECIMAL32; 123 case "DECIMAL64": 124 return MathContext.DECIMAL64; 125 case "DECIMAL128": 126 return MathContext.DECIMAL128; 127 default: 128 throw new UnsupportedOperationException(); 129 } 130 } 131 132 static BigDecimal bigDecimal(MethodHandles.Lookup l, String name, Class<?> type, 133 String value, MathContext mc) { 134 return new BigDecimal(value, mc); 135 } 136 137 static String condyWithCondy(MethodHandles.Lookup l, String name, Class<?> type, 138 BigDecimal d) { 139 return new StringJoiner("-") 140 .add(name) 141 .add(type.getSimpleName()) 142 .add(d.toString()) 143 .add(Integer.toString(d.precision())) 144 .toString(); 145 } 146 147 static <E> int bigDecimalPoolHelper(String value, String mc, PoolHelper<String, String, E> P) { 148 BSMInfo bi = BSMInfo.of("bigDecimal"); 149 return P.putDynamicConstant("big-decimal", "Ljava/math/BigDecimal;", InstructionHelper.csym(L.lookupClass()), bi.methodName, bi.descriptor, 150 S -> S.add(value, PoolHelper::putString) 151 .add(mc, (P2, s) -> { 152 return mathContextPoolHelper(s, P2); 153 })); 154 } 155 156 static <E> int mathContextPoolHelper(String mc, PoolHelper<String, String, E> P) { 157 BSMInfo bi = BSMInfo.of("mathContext"); 158 return P.putDynamicConstant(mc, "Ljava/math/MathContext;", InstructionHelper.csym(L.lookupClass()), bi.methodName, bi.descriptor, 159 S -> { 160 }); 161 } 162 163 @Test 164 public void testCondyWithCondy() throws Throwable { 165 BSMInfo bi = BSMInfo.of("condyWithCondy"); 166 167 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 168 L, "big-decimal-math-context", String.class, 169 bi.methodName, bi.handle.type(), 170 S -> S.add(null, (P, v) -> { 171 return bigDecimalPoolHelper("3.14159265358979323846", "DECIMAL32", P); 172 })); 173 Assert.assertEquals(mh.invoke(), "big-decimal-math-context-String-3.141593-7"); 174 } 175 176 177 static ConstantCallSite indyWithCondy(MethodHandles.Lookup l, String name, MethodType type, 178 BigDecimal d) { 179 String s = new StringJoiner("-") 180 .add(name) 181 .add(type.toMethodDescriptorString()) 182 .add(d.toString()) 183 .add(Integer.toString(d.precision())) 184 .toString(); 185 return new ConstantCallSite(MethodHandles.constant(String.class, s)); 186 } 187 188 @Test 189 public void testIndyWithCondy() throws Throwable { 190 BSMInfo bi = BSMInfo.of("indyWithCondy"); 191 192 MethodHandle mh = InstructionHelper.invokedynamic( 193 L, "big-decimal-math-context", methodType(String.class), 194 bi.methodName, bi.handle.type(), 195 S -> S.add(null, (P, v) -> { 196 return bigDecimalPoolHelper("3.14159265358979323846", "DECIMAL32", P); 197 })); 198 Assert.assertEquals(mh.invoke(), "big-decimal-math-context-()Ljava/lang/String;-3.141593-7"); 199 } 200 }