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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.mvt; 27 28 import java.lang.invoke.MethodHandle; 29 import java.lang.invoke.MethodHandles.Lookup; 30 import java.lang.invoke.MethodType; 31 import java.lang.reflect.Field; 32 33 import valhalla.shady.MinimalValueTypes_1_0; 34 import valhalla.shady.ValueTypeHolder; 35 36 /** 37 * Value type reflection support. 38 */ 39 public class ValueType<T> { 40 /** 41 * Returns a {@code ValueType} object representing the specified 42 * value-capable class. 43 * 44 * @param vcc Value-capable class 45 * @param <T> Value type 46 * @return a {@code ValueType} object representing the specified 47 * value-capable class. 48 * 49 * @throws IllegalArgumentException if the specified {@code vcc} 50 * is not a value-capable class. 51 */ 52 public static <T> ValueType<T> forClass(Class<T> vcc) { 53 return new ValueType<>(MinimalValueTypes_1_0.getValueFor(vcc)); 54 } 55 56 /** 57 * Returns {@code true} if the specified class is value-capable class. 58 * 59 * @param c a Class 60 * @return true if the specified class is a value-capable class. 61 */ 62 public static boolean classHasValueType(Class<?> c) { 63 if (!MinimalValueTypes_1_0.isValueCapable(c)) { 64 return false; 65 } 66 return MinimalValueTypes_1_0.getValueTypeClass(c) != null; 67 } 68 69 private final ValueTypeHolder<T> valueTypeHolder; 70 private ValueType(ValueTypeHolder<T> vt) { 71 this.valueTypeHolder = vt; 72 } 73 74 /** 75 * Returns the value-capable class of this value type. 76 * 77 * @return the value-capable class of this value type. 78 */ 79 public Class<T> boxClass() { 80 return valueTypeHolder.boxClass(); 81 } 82 83 /** 84 * Returns the derived value type of this value type. 85 * 86 * @return the derived value type of this value type. 87 */ 88 public Class<?> valueClass() { 89 return valueTypeHolder.valueClass(); 90 } 91 92 /** 93 * Returns an array class of this value type. 94 * 95 * @return an array class of this value type. 96 */ 97 public Class<?> arrayValueClass() { 98 return arrayValueClass(1); 99 } 100 101 /** 102 * Returns an array class of the specified dimension for this value type. 103 * 104 * @return an array class of the specified dimension for this value type. 105 */ 106 public Class<?> arrayValueClass(int dims) { 107 String dimsStr = "[[[[[[[[[[[[[[[["; 108 if (dims < 1 || dims > 16) { 109 throw new IllegalArgumentException("cannot create array class for dimension > 16"); 110 } 111 String cn = dimsStr.substring(0, dims) + "Q" + valueClass().getName() + ";"; 112 return MinimalValueTypes_1_0.loadValueTypeClass(boxClass(), cn); 113 } 114 115 /** 116 * Returns a string representation of this value type. 117 * 118 * @return a string representation of this value type. 119 */ 120 public String toString() { 121 return valueTypeHolder.toString(); 122 } 123 124 public static <T> ValueType<T> make(Lookup lookup, 125 String name, 126 String[] fieldNames, 127 Class<?>... fieldTypes) 128 throws ReflectiveOperationException 129 { 130 if (fieldNames.length != fieldTypes.length) { 131 throw new IllegalArgumentException("Field names length and field types length must match"); 132 } 133 if (!(fieldNames.length > 0)) { 134 throw new IllegalArgumentException("Field length must be greater than zero"); 135 } 136 Class<T> vtClass = ValueTypeHolder.makeValueTypeClass(lookup, name, fieldNames, fieldTypes); 137 return forClass(vtClass); 138 } 139 140 // ()Q 141 public MethodHandle findConstructor(Lookup lookup, MethodType type) 142 throws NoSuchMethodException, IllegalAccessException { 143 return valueTypeHolder.findConstructor(lookup, type); 144 } 145 146 // (F1, ..., Fn)Q, fromDefault == true 147 // (Q, F1, ..., Fn)Q, fromDefault == false 148 public MethodHandle unreflectWithers(Lookup lookup, 149 boolean fromDefault, 150 Field... fields) 151 throws NoSuchFieldException, IllegalAccessException { 152 return valueTypeHolder.unreflectWithers(lookup, fromDefault, fields); 153 } 154 155 // (Q, T)Q 156 public MethodHandle findWither(Lookup lookup, String name, Class<?> type) 157 throws NoSuchFieldException, IllegalAccessException { 158 return valueTypeHolder.findWither(lookup, name, type); 159 } 160 161 public MethodHandle unbox() { 162 return valueTypeHolder.unbox(); 163 } 164 165 public MethodHandle box() { 166 return valueTypeHolder.box(); 167 } 168 169 public MethodHandle newArray() { 170 return valueTypeHolder.newArray(); 171 } 172 173 public MethodHandle arrayGetter() { 174 return valueTypeHolder.arrayGetter(); 175 } 176 177 public MethodHandle arraySetter() { 178 return valueTypeHolder.arraySetter(); 179 } 180 181 public MethodHandle newMultiArray(int dims) { 182 return valueTypeHolder.newMultiArray(dims); 183 } 184 185 public MethodHandle arrayLength() { 186 return valueTypeHolder.arrayLength(); 187 } 188 189 public MethodHandle identity() { 190 return valueTypeHolder.identity(); 191 } 192 193 public MethodHandle findGetter(Lookup lookup, String name, Class<?> type) 194 throws NoSuchFieldException, IllegalAccessException { 195 return valueTypeHolder.findGetter(lookup, name, type); 196 } 197 198 public MethodHandle substitutabilityTest() { 199 return valueTypeHolder.substitutabilityTest(); 200 } 201 202 public MethodHandle substitutabilityHashCode() { 203 return valueTypeHolder.substitutabilityHashCode(); 204 } 205 206 public MethodHandle defaultValueConstant() { 207 return valueTypeHolder.defaultValueConstant(); 208 } 209 210 public Field[] valueFields() { 211 return valueTypeHolder.valueFields(); 212 } 213 }