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