23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.VerifyAccess;
29 import static java.lang.invoke.LambdaForm.*;
30
31 import sun.invoke.util.Wrapper;
32
33 import java.io.*;
34 import java.util.*;
35
36 import jdk.internal.org.objectweb.asm.*;
37
38 import java.lang.reflect.*;
39 import static java.lang.invoke.MethodHandleStatics.*;
40 import static java.lang.invoke.MethodHandleNatives.Constants.*;
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import sun.invoke.util.VerifyType;
43
44 /**
45 * Code generation backend for LambdaForm.
46 * <p>
47 * @author John Rose, JSR 292 EG
48 */
49 class InvokerBytecodeGenerator {
50 /** Define class names for convenience. */
51 private static final String MH = "java/lang/invoke/MethodHandle";
52 private static final String MHI = "java/lang/invoke/MethodHandleImpl";
53 private static final String LF = "java/lang/invoke/LambdaForm";
54 private static final String LFN = "java/lang/invoke/LambdaForm$Name";
55 private static final String CLS = "java/lang/Class";
56 private static final String OBJ = "java/lang/Object";
57 private static final String OBJARY = "[Ljava/lang/Object;";
58
59 private static final String LF_SIG = "L" + LF + ";";
60 private static final String LFN_SIG = "L" + LFN + ";";
61 private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
62 private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
577 }
578
579 static private Class<?>[] STATICALLY_INVOCABLE_PACKAGES = {
580 // Sample classes from each package we are willing to bind to statically:
581 java.lang.Object.class,
582 java.util.Arrays.class,
583 sun.misc.Unsafe.class
584 //MethodHandle.class already covered
585 };
586
587 static boolean isStaticallyInvocable(MemberName member) {
588 if (member == null) return false;
589 if (member.isConstructor()) return false;
590 Class<?> cls = member.getDeclaringClass();
591 if (cls.isArray() || cls.isPrimitive())
592 return false; // FIXME
593 if (cls.isAnonymousClass() || cls.isLocalClass())
594 return false; // inner class of some sort
595 if (cls.getClassLoader() != MethodHandle.class.getClassLoader())
596 return false; // not on BCP
597 MethodType mtype = member.getMethodOrFieldType();
598 if (!isStaticallyNameable(mtype.returnType()))
599 return false;
600 for (Class<?> ptype : mtype.parameterArray())
601 if (!isStaticallyNameable(ptype))
602 return false;
603 if (!member.isPrivate() && VerifyAccess.isSamePackage(MethodHandle.class, cls))
604 return true; // in java.lang.invoke package
605 if (member.isPublic() && isStaticallyNameable(cls))
606 return true;
607 return false;
608 }
609
610 static boolean isStaticallyNameable(Class<?> cls) {
611 while (cls.isArray())
612 cls = cls.getComponentType();
613 if (cls.isPrimitive())
614 return true; // int[].class, for example
615 // could use VerifyAccess.isClassAccessible but the following is a safe approximation
616 if (cls.getClassLoader() != Object.class.getClassLoader())
617 return false;
618 if (VerifyAccess.isSamePackage(MethodHandle.class, cls))
619 return true;
620 if (!Modifier.isPublic(cls.getModifiers()))
621 return false;
622 for (Class<?> pkgcls : STATICALLY_INVOCABLE_PACKAGES) {
623 if (VerifyAccess.isSamePackage(pkgcls, cls))
624 return true;
625 }
626 return false;
627 }
628
629 /**
630 * Emit an invoke for the given name, using the MemberName directly.
631 */
632 void emitStaticInvoke(MemberName member, Name name) {
633 assert(member.equals(name.function.member()));
634 String cname = getInternalName(member.getDeclaringClass());
|
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.VerifyAccess;
29 import static java.lang.invoke.LambdaForm.*;
30
31 import sun.invoke.util.Wrapper;
32
33 import java.io.*;
34 import java.util.*;
35
36 import jdk.internal.org.objectweb.asm.*;
37
38 import java.lang.reflect.*;
39 import static java.lang.invoke.MethodHandleStatics.*;
40 import static java.lang.invoke.MethodHandleNatives.Constants.*;
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import sun.invoke.util.VerifyType;
43 import sun.reflect.misc.ReflectUtil;
44
45 /**
46 * Code generation backend for LambdaForm.
47 * <p>
48 * @author John Rose, JSR 292 EG
49 */
50 class InvokerBytecodeGenerator {
51 /** Define class names for convenience. */
52 private static final String MH = "java/lang/invoke/MethodHandle";
53 private static final String MHI = "java/lang/invoke/MethodHandleImpl";
54 private static final String LF = "java/lang/invoke/LambdaForm";
55 private static final String LFN = "java/lang/invoke/LambdaForm$Name";
56 private static final String CLS = "java/lang/Class";
57 private static final String OBJ = "java/lang/Object";
58 private static final String OBJARY = "[Ljava/lang/Object;";
59
60 private static final String LF_SIG = "L" + LF + ";";
61 private static final String LFN_SIG = "L" + LFN + ";";
62 private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
63 private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
578 }
579
580 static private Class<?>[] STATICALLY_INVOCABLE_PACKAGES = {
581 // Sample classes from each package we are willing to bind to statically:
582 java.lang.Object.class,
583 java.util.Arrays.class,
584 sun.misc.Unsafe.class
585 //MethodHandle.class already covered
586 };
587
588 static boolean isStaticallyInvocable(MemberName member) {
589 if (member == null) return false;
590 if (member.isConstructor()) return false;
591 Class<?> cls = member.getDeclaringClass();
592 if (cls.isArray() || cls.isPrimitive())
593 return false; // FIXME
594 if (cls.isAnonymousClass() || cls.isLocalClass())
595 return false; // inner class of some sort
596 if (cls.getClassLoader() != MethodHandle.class.getClassLoader())
597 return false; // not on BCP
598 if (ReflectUtil.isVMAnonymousClass(cls)) // FIXME: switch to supported API once it is added
599 return false;
600 MethodType mtype = member.getMethodOrFieldType();
601 if (!isStaticallyNameable(mtype.returnType()))
602 return false;
603 for (Class<?> ptype : mtype.parameterArray())
604 if (!isStaticallyNameable(ptype))
605 return false;
606 if (!member.isPrivate() && VerifyAccess.isSamePackage(MethodHandle.class, cls))
607 return true; // in java.lang.invoke package
608 if (member.isPublic() && isStaticallyNameable(cls))
609 return true;
610 return false;
611 }
612
613 static boolean isStaticallyNameable(Class<?> cls) {
614 while (cls.isArray())
615 cls = cls.getComponentType();
616 if (cls.isPrimitive())
617 return true; // int[].class, for example
618 if (ReflectUtil.isVMAnonymousClass(cls)) // FIXME: switch to supported API once it is added
619 return false;
620 // could use VerifyAccess.isClassAccessible but the following is a safe approximation
621 if (cls.getClassLoader() != Object.class.getClassLoader())
622 return false;
623 if (VerifyAccess.isSamePackage(MethodHandle.class, cls))
624 return true;
625 if (!Modifier.isPublic(cls.getModifiers()))
626 return false;
627 for (Class<?> pkgcls : STATICALLY_INVOCABLE_PACKAGES) {
628 if (VerifyAccess.isSamePackage(pkgcls, cls))
629 return true;
630 }
631 return false;
632 }
633
634 /**
635 * Emit an invoke for the given name, using the MemberName directly.
636 */
637 void emitStaticInvoke(MemberName member, Name name) {
638 assert(member.equals(name.function.member()));
639 String cname = getInternalName(member.getDeclaringClass());
|