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