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);
|