< prev index next >

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

Print this page




   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 java.lang.invoke;
  27 
  28 import jdk.experimental.value.ValueType;
  29 import jdk.internal.misc.JavaLangInvokeAccess;
  30 import jdk.internal.misc.SharedSecrets;
  31 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  32 import jdk.internal.org.objectweb.asm.ClassWriter;
  33 import jdk.internal.org.objectweb.asm.MethodVisitor;
  34 import jdk.internal.reflect.CallerSensitive;
  35 import jdk.internal.reflect.Reflection;
  36 import jdk.internal.vm.annotation.ForceInline;
  37 import jdk.internal.vm.annotation.Stable;
  38 import sun.invoke.empty.Empty;
  39 import sun.invoke.util.ValueConversions;
  40 import sun.invoke.util.VerifyType;
  41 import sun.invoke.util.Wrapper;
  42 import valhalla.shady.MinimalValueTypes_1_0;

  43 
  44 import java.lang.reflect.Array;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.Iterator;
  48 import java.util.List;
  49 import java.util.Map;
  50 import java.util.function.Function;
  51 import java.util.stream.Stream;
  52 
  53 import static java.lang.invoke.LambdaForm.*;
  54 import static java.lang.invoke.MethodHandleStatics.*;
  55 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  56 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  57 
  58 /**
  59  * Trusted implementation code for MethodHandle.
  60  * @author jrose
  61  */
  62 /*non-public*/ abstract class MethodHandleImpl {


 417                 convSpecs[i] = valueConversion(src, dst, strict, monobox);
 418             }
 419         }
 420         return convSpecs;
 421     }
 422     static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
 423                                             boolean strict) {
 424         return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false);
 425     }
 426 
 427     /**
 428      * Find a conversion function from the given source to the given destination.
 429      * This conversion function will be used as a LF NamedFunction.
 430      * Return a Class object if a simple cast is needed.
 431      * Return void.class if void is involved.
 432      */
 433     static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
 434         assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict));  // caller responsibility
 435         if (dst == void.class)
 436             return dst;
 437         ValueType<?> srcVT = getValueFor(src);
 438         ValueType<?> dstVT = getValueFor(dst);
 439         MethodHandle fn;
 440         if (src.isPrimitive()) {
 441             if (src == void.class) {
 442                 return void.class;  // caller must recognize this specially
 443             } else if (dst.isPrimitive()) {
 444                 // Examples: int->byte, byte->int, boolean->int (!strict)
 445                 fn = ValueConversions.convertPrimitive(src, dst);
 446             } else {
 447                 // Examples: int->Integer, boolean->Object, float->Number
 448                 Wrapper wsrc = Wrapper.forPrimitiveType(src);
 449                 fn = ValueConversions.boxExact(wsrc);
 450                 assert(fn.type().parameterType(0) == wsrc.primitiveType());
 451                 assert(fn.type().returnType() == wsrc.wrapperType());
 452                 if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
 453                     // Corner case, such as int->Long, which will probably fail.
 454                     MethodType mt = MethodType.methodType(dst, src);
 455                     if (strict)
 456                         fn = fn.asType(mt);
 457                     else
 458                         fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false);


 479                         : ValueConversions.unboxCast(wdst));
 480             }
 481         } else if (dstVT != null) {
 482             if (dstVT.boxClass().equals(src) || src.equals(Object.class)) {
 483                 //unbox
 484                 fn = dstVT.unbox();
 485             } else {
 486                 throw new IllegalArgumentException("Cannot unbox class " + src + " to value " + dst);
 487             }
 488         } else {
 489             // Simple reference conversion.
 490             // Note:  Do not check for a class hierarchy relation
 491             // between src and dst.  In all cases a 'null' argument
 492             // will pass the cast conversion.
 493             return dst;
 494         }
 495         assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
 496         return fn;
 497     }
 498 
 499     @SuppressWarnings("unchecked")
 500     static <Z> ValueType<Z> getValueFor(Class<Z> c) {
 501         try {
 502             if (MinimalValueTypes_1_0.isValueType(c)) {
 503                 return (ValueType<Z>)ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(c));
 504             } else {
 505                 return null;
 506             }
 507         } catch (Throwable ex) {
 508             return null;
 509         }
 510     }
 511 
 512     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
 513         MethodType type = target.type();
 514         int last = type.parameterCount() - 1;
 515         if (type.parameterType(last) != arrayType)
 516             target = target.asType(type.changeParameterType(last, arrayType));
 517         target = target.asFixedArity();  // make sure this attribute is turned off
 518         return new AsVarargsCollector(target, arrayType);
 519     }
 520 
 521     private static final class AsVarargsCollector extends DelegatingMethodHandle {
 522         private final MethodHandle target;
 523         private final Class<?> arrayType;
 524         private @Stable MethodHandle asCollectorCache;
 525 
 526         AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
 527             this(target.type(), target, arrayType);
 528         }
 529         AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
 530             super(type, target);
 531             this.target = target;


1804 
1805             @Override
1806             public byte[] generateInvokersHolderClassBytes(final String className,
1807                     MethodType[] methodTypes) {
1808                 return GenerateJLIClassesHelper
1809                         .generateInvokersHolderClassBytes(className, methodTypes);
1810             }
1811         });
1812     }
1813 
1814     /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
1815     private static MethodHandle unboxResultHandle(Class<?> returnType) {
1816         if (returnType.isPrimitive()) {
1817             if (returnType == void.class) {
1818                 return ValueConversions.ignore();
1819             } else {
1820                 Wrapper w = Wrapper.forPrimitiveType(returnType);
1821                 return ValueConversions.unboxExact(w);
1822             }
1823         } else if (MinimalValueTypes_1_0.isValueType(returnType)) {
1824             return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(returnType)).unbox();
1825         } else {
1826             return MethodHandles.identity(Object.class);
1827         }
1828     }
1829 
1830     /**
1831      * Assembles a loop method handle from the given handles and type information.
1832      *
1833      * @param tloop the return type of the loop.
1834      * @param targs types of the arguments to be passed to the loop.
1835      * @param init sanitized array of initializers for loop-local variables.
1836      * @param step sanitited array of loop bodies.
1837      * @param pred sanitized array of predicates.
1838      * @param fini sanitized array of loop finalizers.
1839      *
1840      * @return a handle that, when invoked, will execute the loop.
1841      */
1842     static MethodHandle makeLoop(Class<?> tloop, List<Class<?>> targs, List<MethodHandle> init, List<MethodHandle> step,
1843                                  List<MethodHandle> pred, List<MethodHandle> fini) {
1844         MethodType type = MethodType.methodType(tloop, targs);




   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 java.lang.invoke;
  27 

  28 import jdk.internal.misc.JavaLangInvokeAccess;
  29 import jdk.internal.misc.SharedSecrets;
  30 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  31 import jdk.internal.org.objectweb.asm.ClassWriter;
  32 import jdk.internal.org.objectweb.asm.MethodVisitor;
  33 import jdk.internal.reflect.CallerSensitive;
  34 import jdk.internal.reflect.Reflection;
  35 import jdk.internal.vm.annotation.ForceInline;
  36 import jdk.internal.vm.annotation.Stable;
  37 import sun.invoke.empty.Empty;
  38 import sun.invoke.util.ValueConversions;
  39 import sun.invoke.util.VerifyType;
  40 import sun.invoke.util.Wrapper;
  41 import valhalla.shady.MinimalValueTypes_1_0;
  42 import valhalla.shady.ValueTypeHolder;
  43 
  44 import java.lang.reflect.Array;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.Iterator;
  48 import java.util.List;
  49 import java.util.Map;
  50 import java.util.function.Function;
  51 import java.util.stream.Stream;
  52 
  53 import static java.lang.invoke.LambdaForm.*;
  54 import static java.lang.invoke.MethodHandleStatics.*;
  55 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  56 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  57 
  58 /**
  59  * Trusted implementation code for MethodHandle.
  60  * @author jrose
  61  */
  62 /*non-public*/ abstract class MethodHandleImpl {


 417                 convSpecs[i] = valueConversion(src, dst, strict, monobox);
 418             }
 419         }
 420         return convSpecs;
 421     }
 422     static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
 423                                             boolean strict) {
 424         return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false);
 425     }
 426 
 427     /**
 428      * Find a conversion function from the given source to the given destination.
 429      * This conversion function will be used as a LF NamedFunction.
 430      * Return a Class object if a simple cast is needed.
 431      * Return void.class if void is involved.
 432      */
 433     static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
 434         assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict));  // caller responsibility
 435         if (dst == void.class)
 436             return dst;
 437         ValueTypeHolder<?> srcVT = MinimalValueTypes_1_0.findValueType(src);
 438         ValueTypeHolder<?> dstVT = MinimalValueTypes_1_0.findValueType(dst);
 439         MethodHandle fn;
 440         if (src.isPrimitive()) {
 441             if (src == void.class) {
 442                 return void.class;  // caller must recognize this specially
 443             } else if (dst.isPrimitive()) {
 444                 // Examples: int->byte, byte->int, boolean->int (!strict)
 445                 fn = ValueConversions.convertPrimitive(src, dst);
 446             } else {
 447                 // Examples: int->Integer, boolean->Object, float->Number
 448                 Wrapper wsrc = Wrapper.forPrimitiveType(src);
 449                 fn = ValueConversions.boxExact(wsrc);
 450                 assert(fn.type().parameterType(0) == wsrc.primitiveType());
 451                 assert(fn.type().returnType() == wsrc.wrapperType());
 452                 if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
 453                     // Corner case, such as int->Long, which will probably fail.
 454                     MethodType mt = MethodType.methodType(dst, src);
 455                     if (strict)
 456                         fn = fn.asType(mt);
 457                     else
 458                         fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false);


 479                         : ValueConversions.unboxCast(wdst));
 480             }
 481         } else if (dstVT != null) {
 482             if (dstVT.boxClass().equals(src) || src.equals(Object.class)) {
 483                 //unbox
 484                 fn = dstVT.unbox();
 485             } else {
 486                 throw new IllegalArgumentException("Cannot unbox class " + src + " to value " + dst);
 487             }
 488         } else {
 489             // Simple reference conversion.
 490             // Note:  Do not check for a class hierarchy relation
 491             // between src and dst.  In all cases a 'null' argument
 492             // will pass the cast conversion.
 493             return dst;
 494         }
 495         assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
 496         return fn;
 497     }
 498 













 499     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
 500         MethodType type = target.type();
 501         int last = type.parameterCount() - 1;
 502         if (type.parameterType(last) != arrayType)
 503             target = target.asType(type.changeParameterType(last, arrayType));
 504         target = target.asFixedArity();  // make sure this attribute is turned off
 505         return new AsVarargsCollector(target, arrayType);
 506     }
 507 
 508     private static final class AsVarargsCollector extends DelegatingMethodHandle {
 509         private final MethodHandle target;
 510         private final Class<?> arrayType;
 511         private @Stable MethodHandle asCollectorCache;
 512 
 513         AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
 514             this(target.type(), target, arrayType);
 515         }
 516         AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
 517             super(type, target);
 518             this.target = target;


1791 
1792             @Override
1793             public byte[] generateInvokersHolderClassBytes(final String className,
1794                     MethodType[] methodTypes) {
1795                 return GenerateJLIClassesHelper
1796                         .generateInvokersHolderClassBytes(className, methodTypes);
1797             }
1798         });
1799     }
1800 
1801     /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
1802     private static MethodHandle unboxResultHandle(Class<?> returnType) {
1803         if (returnType.isPrimitive()) {
1804             if (returnType == void.class) {
1805                 return ValueConversions.ignore();
1806             } else {
1807                 Wrapper w = Wrapper.forPrimitiveType(returnType);
1808                 return ValueConversions.unboxExact(w);
1809             }
1810         } else if (MinimalValueTypes_1_0.isValueType(returnType)) {
1811             return MinimalValueTypes_1_0.findValueType(returnType).unbox();
1812         } else {
1813             return MethodHandles.identity(Object.class);
1814         }
1815     }
1816 
1817     /**
1818      * Assembles a loop method handle from the given handles and type information.
1819      *
1820      * @param tloop the return type of the loop.
1821      * @param targs types of the arguments to be passed to the loop.
1822      * @param init sanitized array of initializers for loop-local variables.
1823      * @param step sanitited array of loop bodies.
1824      * @param pred sanitized array of predicates.
1825      * @param fini sanitized array of loop finalizers.
1826      *
1827      * @return a handle that, when invoked, will execute the loop.
1828      */
1829     static MethodHandle makeLoop(Class<?> tloop, List<Class<?>> targs, List<MethodHandle> init, List<MethodHandle> step,
1830                                  List<MethodHandle> pred, List<MethodHandle> fini) {
1831         MethodType type = MethodType.methodType(tloop, targs);


< prev index next >