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