src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 9490 : 8037210: Get rid of char-based descriptions 'J' of basic types
Reviewed-by: ?
Contributed-by: john.r.rose@oracle.com
rev 9491 : 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Reviewed-by: ?
Contributed-by: john.r.rose@oracle.com


  35 import sun.invoke.util.Wrapper;
  36 import sun.reflect.CallerSensitive;
  37 import sun.reflect.Reflection;
  38 import static java.lang.invoke.LambdaForm.*;
  39 import static java.lang.invoke.MethodHandleStatics.*;
  40 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  41 
  42 /**
  43  * Trusted implementation code for MethodHandle.
  44  * @author jrose
  45  */
  46 /*non-public*/ abstract class MethodHandleImpl {
  47     /// Factory methods to create method handles:
  48 
  49     static void initStatics() {
  50         // Trigger selected static initializations.
  51         MemberName.Factory.INSTANCE.getClass();
  52     }
  53 
  54     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {


  55         if (!arrayClass.isArray())
  56             throw newIllegalArgumentException("not an array: "+arrayClass);
  57         MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
  58         MethodType srcType = accessor.type().erase();
  59         MethodType lambdaType = srcType.invokerType();
  60         Name[] names = arguments(1, lambdaType);
  61         Name[] args  = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
  62         names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
  63         LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
  64         MethodHandle mh = SimpleMethodHandle.make(srcType, form);
  65         if (ArrayAccessor.needCast(arrayClass)) {
  66             mh = mh.bindTo(arrayClass);


  67         }
  68         mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
  69         return mh;
  70     }
  71 
  72     static final class ArrayAccessor {
  73         /// Support for array element access
  74         static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>();  // TODO use it
  75         static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>();  // TODO use it












  76 
  77         static int     getElementI(int[]     a, int i)            { return              a[i]; }
  78         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
  79         static float   getElementF(float[]   a, int i)            { return              a[i]; }
  80         static double  getElementD(double[]  a, int i)            { return              a[i]; }
  81         static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
  82         static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
  83         static short   getElementS(short[]   a, int i)            { return              a[i]; }
  84         static char    getElementC(char[]    a, int i)            { return              a[i]; }
  85         static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
  86 
  87         static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
  88         static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
  89         static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
  90         static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
  91         static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
  92         static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
  93         static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
  94         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
  95         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
  96 
  97         static Object  getElementL(Class<?> arrayClass, Object[] a, int i)           { arrayClass.cast(a); return a[i]; }
  98         static void    setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
  99 
 100         // Weakly typed wrappers of Object[] accessors:
 101         static Object  getElementL(Object    a, int i)            { return getElementL((Object[])a, i); }
 102         static void    setElementL(Object    a, int i, Object  x) {        setElementL((Object[]) a, i, x); }
 103         static Object  getElementL(Object   arrayClass, Object a, int i)             { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
 104         static void    setElementL(Object   arrayClass, Object a, int i, Object x)   {        setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
 105 
 106         static boolean needCast(Class<?> arrayClass) {
 107             Class<?> elemClass = arrayClass.getComponentType();
 108             return !elemClass.isPrimitive() && elemClass != Object.class;
 109         }
 110         static String name(Class<?> arrayClass, boolean isSetter) {
 111             Class<?> elemClass = arrayClass.getComponentType();
 112             if (elemClass == null)  throw new IllegalArgumentException();
 113             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
 114         }
 115         static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
 116         static MethodType type(Class<?> arrayClass, boolean isSetter) {
 117             Class<?> elemClass = arrayClass.getComponentType();
 118             Class<?> arrayArgClass = arrayClass;
 119             if (!elemClass.isPrimitive()) {
 120                 arrayArgClass = Object[].class;
 121                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 122                     arrayArgClass = Object.class;
 123             }
 124             if (!needCast(arrayClass)) {
 125                 return !isSetter ?
 126                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
 127                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
 128             } else {
 129                 Class<?> classArgClass = Class.class;
 130                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 131                     classArgClass = Object.class;
 132                 return !isSetter ?
 133                     MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
 134                     MethodType.methodType(void.class,   classArgClass, arrayArgClass, int.class, Object.class);
 135             }
 136         }
 137         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
 138             Class<?> elemClass = arrayClass.getComponentType();
 139             return !isSetter ?
 140                     MethodType.methodType(elemClass,  arrayClass, int.class) :
 141                     MethodType.methodType(void.class, arrayClass, int.class, elemClass);
 142         }
 143         static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
 144             String     name = name(arrayClass, isSetter);
 145             MethodType type = type(arrayClass, isSetter);
 146             try {
 147                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
 148             } catch (ReflectiveOperationException ex) {
 149                 throw uncaughtException(ex);
 150             }
 151         }
 152     }
 153 
 154     /**
 155      * Create a JVM-level adapter method handle to conform the given method


 162      * @param level which strength of conversion is allowed
 163      * @return an adapter to the original handle with the desired new type,
 164      *          or the original target if the types are already identical
 165      *          or null if the adaptation cannot be made
 166      */
 167     static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
 168         assert(level >= 0 && level <= 2);
 169         MethodType dstType = target.type();
 170         assert(dstType.parameterCount() == target.type().parameterCount());
 171         if (srcType == dstType)
 172             return target;
 173 
 174         // Calculate extra arguments (temporaries) required in the names array.
 175         // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
 176         final int INARG_COUNT = srcType.parameterCount();
 177         int conversions = 0;
 178         boolean[] needConv = new boolean[1+INARG_COUNT];
 179         for (int i = 0; i <= INARG_COUNT; i++) {
 180             Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
 181             Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
 182             if (!VerifyType.isNullConversion(src, dst) ||
 183                 level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
 184                 needConv[i] = true;
 185                 conversions++;
 186             }
 187         }
 188         boolean retConv = needConv[INARG_COUNT];




 189 
 190         final int IN_MH         = 0;
 191         final int INARG_BASE    = 1;
 192         final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
 193         final int NAME_LIMIT    = INARG_LIMIT + conversions + 1;
 194         final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
 195         final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;

 196 
 197         // Now build a LambdaForm.
 198         MethodType lambdaType = srcType.basicType().invokerType();
 199         Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
 200 
 201         // Collect the arguments to the outgoing call, maybe with conversions:
 202         final int OUTARG_BASE = 0;  // target MH is Name.function, name Name.arguments[0]
 203         Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
 204 
 205         int nameCursor = INARG_LIMIT;
 206         for (int i = 0; i < INARG_COUNT; i++) {
 207             Class<?> src = srcType.parameterType(i);
 208             Class<?> dst = dstType.parameterType(i);
 209 
 210             if (!needConv[i]) {
 211                 // do nothing: difference is trivial
 212                 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
 213                 continue;
 214             }
 215 
 216             // Tricky case analysis follows.
 217             MethodHandle fn = null;
 218             if (src.isPrimitive()) {
 219                 if (dst.isPrimitive()) {
 220                     fn = ValueConversions.convertPrimitive(src, dst);
 221                 } else {
 222                     Wrapper w = Wrapper.forPrimitiveType(src);
 223                     MethodHandle boxMethod = ValueConversions.box(w);
 224                     if (dst == w.wrapperType())
 225                         fn = boxMethod;
 226                     else
 227                         fn = boxMethod.asType(MethodType.methodType(dst, src));
 228                 }
 229             } else {
 230                 if (dst.isPrimitive()) {
 231                     // Caller has boxed a primitive.  Unbox it for the target.
 232                     Wrapper w = Wrapper.forPrimitiveType(dst);
 233                     if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
 234                         fn = ValueConversions.unbox(dst);
 235                     } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
 236                         // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
 237                         // must include additional conversions
 238                         // src must be examined at runtime, to detect Byte, Character, etc.
 239                         MethodHandle unboxMethod = (level == 1
 240                                                     ? ValueConversions.unbox(dst)
 241                                                     : ValueConversions.unboxCast(dst));
 242                         fn = unboxMethod;
 243                     } else {
 244                         // Example: Byte->int
 245                         // Do this by reformulating the problem to Byte->byte.
 246                         Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
 247                         MethodHandle unbox = ValueConversions.unbox(srcPrim);
 248                         // Compose the two conversions.  FIXME:  should make two Names for this job
 249                         fn = unbox.asType(MethodType.methodType(dst, src));
 250                     }
 251                 } else {
 252                     // Simple reference conversion.
 253                     // Note:  Do not check for a class hierarchy relation


 272         } else {
 273             Class<?> needReturn = srcType.returnType();
 274             Class<?> haveReturn = dstType.returnType();
 275             MethodHandle fn;
 276             Object[] arg = { names[OUT_CALL] };
 277             if (haveReturn == void.class) {
 278                 // synthesize a zero value for the given void
 279                 Object zero = Wrapper.forBasicType(needReturn).zero();
 280                 fn = MethodHandles.constant(needReturn, zero);
 281                 arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
 282             } else {
 283                 MethodHandle identity = MethodHandles.identity(needReturn);
 284                 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
 285                 fn = makePairwiseConvert(identity, needConversion, level);
 286             }
 287             assert(names[RETURN_CONV] == null);
 288             names[RETURN_CONV] = new Name(fn, arg);
 289             assert(RETURN_CONV == names.length-1);
 290         }
 291 
 292         LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
 293         return SimpleMethodHandle.make(srcType, form);
 294     }
 295 
 296     /**
 297      * Identity function, with reference cast.
 298      * @param t an arbitrary reference type
 299      * @param x an arbitrary reference value
 300      * @return the same value x
 301      */
 302     @ForceInline
 303     @SuppressWarnings("unchecked")
 304     static <T,U> T castReference(Class<? extends T> t, U x) {
 305         // inlined Class.cast because we can't ForceInline it
 306         if (x != null && !t.isInstance(x))
 307             throw newClassCastException(t, x);
 308         return (T) x;
 309     }
 310 
 311     private static ClassCastException newClassCastException(Class<?> t, Object obj) {
 312         return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());




  35 import sun.invoke.util.Wrapper;
  36 import sun.reflect.CallerSensitive;
  37 import sun.reflect.Reflection;
  38 import static java.lang.invoke.LambdaForm.*;
  39 import static java.lang.invoke.MethodHandleStatics.*;
  40 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  41 
  42 /**
  43  * Trusted implementation code for MethodHandle.
  44  * @author jrose
  45  */
  46 /*non-public*/ abstract class MethodHandleImpl {
  47     /// Factory methods to create method handles:
  48 
  49     static void initStatics() {
  50         // Trigger selected static initializations.
  51         MemberName.Factory.INSTANCE.getClass();
  52     }
  53 
  54     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
  55         if (arrayClass == Object[].class)
  56             return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
  57         if (!arrayClass.isArray())
  58             throw newIllegalArgumentException("not an array: "+arrayClass);
  59         MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
  60         int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
  61         MethodHandle mh = cache[cacheIndex];
  62         if (mh != null)  return mh;
  63         mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
  64         MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
  65         if (mh.type() != correctType) {
  66             assert(mh.type().parameterType(0) == Object[].class);
  67             assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
  68             assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
  69             // safe to view non-strictly, because element type follows from array type
  70             mh = mh.viewAsType(correctType);
  71         }
  72         cache[cacheIndex] = mh;
  73         return mh;
  74     }
  75 
  76     static final class ArrayAccessor {
  77         /// Support for array element access
  78         static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
  79         static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
  80                 = new ClassValue<MethodHandle[]>() {
  81                     @Override
  82                     protected MethodHandle[] computeValue(Class<?> type) {
  83                         return new MethodHandle[INDEX_LIMIT];
  84                     }
  85                 };
  86         static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER;
  87         static {
  88             MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
  89             cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = getAccessor(Object[].class, false);
  90             cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = getAccessor(Object[].class, true);
  91         }
  92 
  93         static int     getElementI(int[]     a, int i)            { return              a[i]; }
  94         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
  95         static float   getElementF(float[]   a, int i)            { return              a[i]; }
  96         static double  getElementD(double[]  a, int i)            { return              a[i]; }
  97         static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
  98         static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
  99         static short   getElementS(short[]   a, int i)            { return              a[i]; }
 100         static char    getElementC(char[]    a, int i)            { return              a[i]; }
 101         static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
 102 
 103         static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
 104         static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
 105         static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
 106         static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
 107         static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
 108         static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
 109         static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
 110         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
 111         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
 112 













 113         static String name(Class<?> arrayClass, boolean isSetter) {
 114             Class<?> elemClass = arrayClass.getComponentType();
 115             if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
 116             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
 117         }

 118         static MethodType type(Class<?> arrayClass, boolean isSetter) {
 119             Class<?> elemClass = arrayClass.getComponentType();
 120             Class<?> arrayArgClass = arrayClass;
 121             if (!elemClass.isPrimitive()) {
 122                 arrayArgClass = Object[].class;
 123                 elemClass = Object.class;

 124             }

 125             return !isSetter ?
 126                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
 127                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);








 128         }
 129         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
 130             Class<?> elemClass = arrayClass.getComponentType();
 131             return !isSetter ?
 132                     MethodType.methodType(elemClass,  arrayClass, int.class) :
 133                     MethodType.methodType(void.class, arrayClass, int.class, elemClass);
 134         }
 135         static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
 136             String     name = name(arrayClass, isSetter);
 137             MethodType type = type(arrayClass, isSetter);
 138             try {
 139                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
 140             } catch (ReflectiveOperationException ex) {
 141                 throw uncaughtException(ex);
 142             }
 143         }
 144     }
 145 
 146     /**
 147      * Create a JVM-level adapter method handle to conform the given method


 154      * @param level which strength of conversion is allowed
 155      * @return an adapter to the original handle with the desired new type,
 156      *          or the original target if the types are already identical
 157      *          or null if the adaptation cannot be made
 158      */
 159     static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
 160         assert(level >= 0 && level <= 2);
 161         MethodType dstType = target.type();
 162         assert(dstType.parameterCount() == target.type().parameterCount());
 163         if (srcType == dstType)
 164             return target;
 165 
 166         // Calculate extra arguments (temporaries) required in the names array.
 167         // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
 168         final int INARG_COUNT = srcType.parameterCount();
 169         int conversions = 0;
 170         boolean[] needConv = new boolean[1+INARG_COUNT];
 171         for (int i = 0; i <= INARG_COUNT; i++) {
 172             Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
 173             Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
 174             if (!VerifyType.isNullConversion(src, dst, false) ||
 175                 level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
 176                 needConv[i] = true;
 177                 conversions++;
 178             }
 179         }
 180         boolean retConv = needConv[INARG_COUNT];
 181         if (retConv && srcType.returnType() == void.class) {
 182             retConv = false;
 183             conversions--;
 184         }
 185 
 186         final int IN_MH         = 0;
 187         final int INARG_BASE    = 1;
 188         final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
 189         final int NAME_LIMIT    = INARG_LIMIT + conversions + 1;
 190         final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
 191         final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
 192         final int RESULT        = (srcType.returnType() == void.class ? -1 : NAME_LIMIT - 1);
 193 
 194         // Now build a LambdaForm.
 195         MethodType lambdaType = srcType.basicType().invokerType();
 196         Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
 197 
 198         // Collect the arguments to the outgoing call, maybe with conversions:
 199         final int OUTARG_BASE = 0;  // target MH is Name.function, name Name.arguments[0]
 200         Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
 201 
 202         int nameCursor = INARG_LIMIT;
 203         for (int i = 0; i < INARG_COUNT; i++) {
 204             Class<?> src = srcType.parameterType(i);
 205             Class<?> dst = dstType.parameterType(i);
 206 
 207             if (!needConv[i]) {
 208                 // do nothing: difference is trivial
 209                 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
 210                 continue;
 211             }
 212 
 213             // Tricky case analysis follows.
 214             MethodHandle fn = null;
 215             if (src.isPrimitive()) {
 216                 if (dst.isPrimitive()) {
 217                     fn = ValueConversions.convertPrimitive(src, dst);
 218                 } else {
 219                     Wrapper w = Wrapper.forPrimitiveType(src);
 220                     MethodHandle boxMethod = ValueConversions.box(w);
 221                     if (dst == w.wrapperType())
 222                         fn = boxMethod;
 223                     else
 224                         fn = boxMethod.asType(MethodType.methodType(dst, src));
 225                 }
 226             } else {
 227                 if (dst.isPrimitive()) {
 228                     // Caller has boxed a primitive.  Unbox it for the target.
 229                     Wrapper w = Wrapper.forPrimitiveType(dst);
 230                     if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType(), false)) {
 231                         fn = ValueConversions.unbox(dst);
 232                     } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
 233                         // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
 234                         // must include additional conversions
 235                         // src must be examined at runtime, to detect Byte, Character, etc.
 236                         MethodHandle unboxMethod = (level == 1
 237                                                     ? ValueConversions.unbox(dst)
 238                                                     : ValueConversions.unboxCast(dst));
 239                         fn = unboxMethod;
 240                     } else {
 241                         // Example: Byte->int
 242                         // Do this by reformulating the problem to Byte->byte.
 243                         Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
 244                         MethodHandle unbox = ValueConversions.unbox(srcPrim);
 245                         // Compose the two conversions.  FIXME:  should make two Names for this job
 246                         fn = unbox.asType(MethodType.methodType(dst, src));
 247                     }
 248                 } else {
 249                     // Simple reference conversion.
 250                     // Note:  Do not check for a class hierarchy relation


 269         } else {
 270             Class<?> needReturn = srcType.returnType();
 271             Class<?> haveReturn = dstType.returnType();
 272             MethodHandle fn;
 273             Object[] arg = { names[OUT_CALL] };
 274             if (haveReturn == void.class) {
 275                 // synthesize a zero value for the given void
 276                 Object zero = Wrapper.forBasicType(needReturn).zero();
 277                 fn = MethodHandles.constant(needReturn, zero);
 278                 arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
 279             } else {
 280                 MethodHandle identity = MethodHandles.identity(needReturn);
 281                 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
 282                 fn = makePairwiseConvert(identity, needConversion, level);
 283             }
 284             assert(names[RETURN_CONV] == null);
 285             names[RETURN_CONV] = new Name(fn, arg);
 286             assert(RETURN_CONV == names.length-1);
 287         }
 288 
 289         LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT);
 290         return SimpleMethodHandle.make(srcType, form);
 291     }
 292 
 293     /**
 294      * Identity function, with reference cast.
 295      * @param t an arbitrary reference type
 296      * @param x an arbitrary reference value
 297      * @return the same value x
 298      */
 299     @ForceInline
 300     @SuppressWarnings("unchecked")
 301     static <T,U> T castReference(Class<? extends T> t, U x) {
 302         // inlined Class.cast because we can't ForceInline it
 303         if (x != null && !t.isInstance(x))
 304             throw newClassCastException(t, x);
 305         return (T) x;
 306     }
 307 
 308     private static ClassCastException newClassCastException(Class<?> t, Object obj) {
 309         return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());


src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File