jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java
changeset 9730 e4b334d47f4b
parent 9646 5ebbe5ab084f
child 9731 d0f7a3e441c4
equal deleted inserted replaced
9646:5ebbe5ab084f 9730:e4b334d47f4b
   139         // Find last non-trivial conversion (if any).
   139         // Find last non-trivial conversion (if any).
   140         int lastConv = newType.parameterCount()-1;
   140         int lastConv = newType.parameterCount()-1;
   141         while (lastConv >= 0) {
   141         while (lastConv >= 0) {
   142             Class<?> src = newType.parameterType(lastConv); // source type
   142             Class<?> src = newType.parameterType(lastConv); // source type
   143             Class<?> dst = oldType.parameterType(lastConv); // destination type
   143             Class<?> dst = oldType.parameterType(lastConv); // destination type
   144             if (VerifyType.isNullConversion(src, dst)) {
   144             if (isTrivialConversion(src, dst, level)) {
   145                 --lastConv;
   145                 --lastConv;
   146             } else {
   146             } else {
   147                 break;
   147                 break;
   148             }
   148             }
   149         }
   149         }
   150 
   150 
   151         Class<?> needReturn = newType.returnType();
   151         Class<?> needReturn = newType.returnType();
   152         Class<?> haveReturn = oldType.returnType();
   152         Class<?> haveReturn = oldType.returnType();
   153         boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn);
   153         boolean retConv = !isTrivialConversion(haveReturn, needReturn, level);
   154 
   154 
   155         // Now build a chain of one or more adapters.
   155         // Now build a chain of one or more adapters.
   156         MethodHandle adapter = target, adapter2;
   156         MethodHandle adapter = target, adapter2;
   157         MethodType midType = oldType;
   157         MethodType midType = oldType;
   158         for (int i = 0; i <= lastConv; i++) {
   158         for (int i = 0; i <= lastConv; i++) {
   159             Class<?> src = newType.parameterType(i); // source type
   159             Class<?> src = newType.parameterType(i); // source type
   160             Class<?> dst = midType.parameterType(i); // destination type
   160             Class<?> dst = midType.parameterType(i); // destination type
   161             if (VerifyType.isNullConversion(src, dst)) {
   161             if (isTrivialConversion(src, dst, level)) {
   162                 // do nothing: difference is trivial
   162                 // do nothing: difference is trivial
   163                 continue;
   163                 continue;
   164             }
   164             }
   165             // Work the current type backward toward the desired caller type:
   165             // Work the current type backward toward the desired caller type:
   166             midType = midType.changeParameterType(i, src);
   166             midType = midType.changeParameterType(i, src);
   217         }
   217         }
   218         assert(adapter.type() == newType);
   218         assert(adapter.type() == newType);
   219         return adapter;
   219         return adapter;
   220     }
   220     }
   221 
   221 
       
   222     private static boolean isTrivialConversion(Class<?> src, Class<?> dst, int level) {
       
   223         if (src == dst || dst == void.class)  return true;
       
   224         if (!VerifyType.isNullConversion(src, dst))  return false;
       
   225         if (level > 1)  return true;  // explicitCastArguments
       
   226         boolean sp = src.isPrimitive();
       
   227         boolean dp = dst.isPrimitive();
       
   228         if (sp != dp)  return false;
       
   229         if (sp) {
       
   230             // in addition to being a null conversion, forbid boolean->int etc.
       
   231             return Wrapper.forPrimitiveType(dst)
       
   232                     .isConvertibleFrom(Wrapper.forPrimitiveType(src));
       
   233         } else {
       
   234             return dst.isAssignableFrom(src);
       
   235         }
       
   236     }
       
   237 
   222     private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) {
   238     private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) {
   223         MethodHandle adjustReturn;
   239         MethodHandle adjustReturn;
   224         if (haveReturn == void.class) {
   240         if (haveReturn == void.class) {
   225             // synthesize a zero value for the given void
   241             // synthesize a zero value for the given void
   226             Object zero = Wrapper.forBasicType(needReturn).zero();
   242             Object zero = Wrapper.forBasicType(needReturn).zero();
   594         Class<?> dst = targetType.parameterType(arg);
   610         Class<?> dst = targetType.parameterType(arg);
   595         if (!canCheckCast(src, castType)
   611         if (!canCheckCast(src, castType)
   596                 || !VerifyType.isNullConversion(castType, dst))
   612                 || !VerifyType.isNullConversion(castType, dst))
   597             return false;
   613             return false;
   598         int diff = diffTypes(newType, targetType, false);
   614         int diff = diffTypes(newType, targetType, false);
   599         return (diff == arg+1);  // arg is sole non-trivial diff
   615         return (diff == arg+1) || (diff == 0);  // arg is sole non-trivial diff
   600     }
   616     }
   601     /** Can an primitive conversion adapter validly convert src to dst? */
   617     /** Can an primitive conversion adapter validly convert src to dst? */
   602     static boolean canCheckCast(Class<?> src, Class<?> dst) {
   618     static boolean canCheckCast(Class<?> src, Class<?> dst) {
   603         return (!src.isPrimitive() && !dst.isPrimitive());
   619         return (!src.isPrimitive() && !dst.isPrimitive());
   604     }
   620     }
  1031     /** Factory method:  Spread selected argument. */
  1047     /** Factory method:  Spread selected argument. */
  1032     static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
  1048     static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
  1033                 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
  1049                 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
  1034         // FIXME: Get rid of newType; derive new arguments from structure of spreadArgType
  1050         // FIXME: Get rid of newType; derive new arguments from structure of spreadArgType
  1035         MethodType targetType = target.type();
  1051         MethodType targetType = target.type();
  1036         if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
  1052         assert(canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
  1037             return null;
  1053             : "[newType, targetType, spreadArgType, spreadArgPos, spreadArgCount] = "
       
  1054               + Arrays.asList(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount);
  1038         // dest is not significant; remove?
  1055         // dest is not significant; remove?
  1039         int dest = T_VOID;
  1056         int dest = T_VOID;
  1040         for (int i = 0; i < spreadArgCount; i++) {
  1057         for (int i = 0; i < spreadArgCount; i++) {
  1041             Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
  1058             Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
  1042             if (arg == null)  arg = Object.class;
  1059             if (arg == null)  arg = Object.class;