1 /* 2 * Copyright (c) 2008, 2013, 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 sun.invoke.util; 27 28 import java.lang.invoke.MethodType; 29 import sun.invoke.empty.Empty; 30 31 /** 32 * This class centralizes information about the JVM verifier 33 * and its requirements about type correctness. 34 * @author jrose 35 */ 36 public class VerifyType { 37 38 private VerifyType() { } // cannot instantiate 39 40 /** 41 * True if a value can be stacked as the source type and unstacked as the 42 * destination type, without violating the JVM's type consistency. 43 * 44 * @param src the type of a stacked value 45 * @param dst the type by which we'd like to treat it 46 * @return whether the retyping can be done without motion or reformatting 47 */ 48 public static boolean isNullConversion(Class<?> src, Class<?> dst) { 49 if (src == dst) return true; 50 // Verifier allows any interface to be treated as Object: 51 if (dst.isInterface()) dst = Object.class; 52 if (src.isInterface()) src = Object.class; 53 if (src == dst) return true; // check again 54 if (dst == void.class) return true; // drop any return value 55 if (isNullType(src)) return !dst.isPrimitive(); 56 if (!src.isPrimitive()) return dst.isAssignableFrom(src); 57 if (!dst.isPrimitive()) return false; 58 // Verifier allows an int to carry byte, short, char, or even boolean: 59 Wrapper sw = Wrapper.forPrimitiveType(src); 60 if (dst == int.class) return sw.isSubwordOrInt(); 61 Wrapper dw = Wrapper.forPrimitiveType(dst); 62 if (!sw.isSubwordOrInt()) return false; 63 if (!dw.isSubwordOrInt()) return false; 64 if (!dw.isSigned() && sw.isSigned()) return false; 65 return dw.bitWidth() > sw.bitWidth(); 66 } 67 68 /** 69 * Specialization of isNullConversion to reference types. 70 * @param src the type of a stacked value 71 * @param dst the reference type by which we'd like to treat it 72 * @return whether the retyping can be done without a cast 73 */ 74 public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) { 75 assert(!dst.isPrimitive()); 76 if (dst.isInterface()) return true; // verifier allows this 77 if (isNullType(src)) return true; 78 return dst.isAssignableFrom(src); 79 } 80 81 /** 82 * Is the given type java.lang.Null or an equivalent null-only type? 83 */ 84 public static boolean isNullType(Class<?> type) { 85 if (type == null) return false; 86 return type == NULL_CLASS 87 // This one may also be used as a null type. 88 // TO DO: Decide if we really want to legitimize it here. 89 // Probably we do, unless java.lang.Null really makes it into Java 7 90 //|| type == Void.class 91 // Locally known null-only class: 92 || type == Empty.class 93 ; 94 } 95 private static final Class<?> NULL_CLASS; 96 static { 97 Class<?> nullClass = null; 98 try { 99 nullClass = Class.forName("java.lang.Null"); 100 } catch (ClassNotFoundException ex) { 101 // OK, we'll cope 102 } 103 NULL_CLASS = nullClass; 104 } 105 106 /** 107 * True if a method handle can receive a call under a slightly different 108 * method type, without moving or reformatting any stack elements. 109 * 110 * @param call the type of call being made 111 * @param recv the type of the method handle receiving the call 112 * @return whether the retyping can be done without motion or reformatting 113 */ 114 public static boolean isNullConversion(MethodType call, MethodType recv) { 115 if (call == recv) return true; 116 int len = call.parameterCount(); 117 if (len != recv.parameterCount()) return false; 118 for (int i = 0; i < len; i++) 119 if (!isNullConversion(call.parameterType(i), recv.parameterType(i))) 120 return false; 121 return isNullConversion(recv.returnType(), call.returnType()); 122 } 123 124 /** 125 * Determine if the JVM verifier allows a value of type call to be 126 * passed to a formal parameter (or return variable) of type recv. 127 * Returns 1 if the verifier allows the types to match without conversion. 128 * Returns -1 if the types can be made to match by a JVM-supported adapter. 129 * Cases supported are: 130 * <ul><li>checkcast 131 * </li><li>conversion between any two integral types (but not floats) 132 * </li><li>unboxing from a wrapper to its corresponding primitive type 133 * </li><li>conversion in either direction between float and double 134 * </li></ul> 135 * (Autoboxing is not supported here; it must be done via Java code.) 136 * Returns 0 otherwise. 137 */ 138 public static int canPassUnchecked(Class<?> src, Class<?> dst) { 139 if (src == dst) 140 return 1; 141 142 if (dst.isPrimitive()) { 143 if (dst == void.class) 144 // Return anything to a caller expecting void. 145 // This is a property of the implementation, which links 146 // return values via a register rather than via a stack push. 147 // This makes it possible to ignore cleanly. 148 return 1; 149 if (src == void.class) 150 return 0; // void-to-something? 151 if (!src.isPrimitive()) 152 // Cannot pass a reference to any primitive type (exc. void). 153 return 0; 154 Wrapper sw = Wrapper.forPrimitiveType(src); 155 Wrapper dw = Wrapper.forPrimitiveType(dst); 156 if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) { 157 if (sw.bitWidth() >= dw.bitWidth()) 158 return -1; // truncation may be required 159 if (!dw.isSigned() && sw.isSigned()) 160 return -1; // sign elimination may be required 161 return 1; 162 } 163 if (src == float.class || dst == float.class) { 164 if (src == double.class || dst == double.class) 165 return -1; // floating conversion may be required 166 else 167 return 0; // other primitive conversions NYI 168 } else { 169 // all fixed-point conversions are supported 170 return 0; 171 } 172 } else if (src.isPrimitive()) { 173 // Cannot pass a primitive to any reference type. 174 // (Maybe allow null.class?) 175 return 0; 176 } 177 178 // Handle reference types in the rest of the block: 179 180 // The verifier treats interfaces exactly like Object. 181 if (isNullReferenceConversion(src, dst)) 182 // pass any reference to object or an arb. interface 183 return 1; 184 // else it's a definite "maybe" (cast is required) 185 return -1; 186 } 187 188 public static boolean isSpreadArgType(Class<?> spreadArg) { 189 return spreadArg.isArray(); 190 } 191 public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) { 192 return spreadArg.getComponentType(); 193 } 194 }