39 import sun.invoke.util.VerifyAccess;
40 import sun.invoke.util.VerifyType;
41 import sun.invoke.util.Wrapper;
42 import sun.reflect.misc.ReflectUtil;
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 + ";";
63
64 /** Name of its super class*/
65 private static final String superName = OBJ;
66
67 /** Name of new class */
68 private final String className;
69
70 /** Name of the source file (for stack trace printing). */
71 private final String sourceFile;
72
73 private final LambdaForm lambdaForm;
74 private final String invokerName;
75 private final MethodType invokerType;
76
77 /** Info about local variables in compiled lambda form */
78 private final int[] localsMap; // index
79 private final BasicType[] localTypes; // basic type
80 private final Class<?>[] localClasses; // type
81
610
611 /**
612 * Generate customized bytecode for a given LambdaForm.
613 */
614 static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
615 InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
616 return g.loadMethod(g.generateCustomizedCodeBytes());
617 }
618
619 /** Determines whether a LambdaForm being compiled contains an intrinsic of some particular type. */
620 private boolean containsIntrinsic(MethodHandleImpl.Intrinsic intr) {
621 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
622 Name name = lambdaForm.names[i];
623 if (name.function.intrinsicName() == intr) {
624 return true;
625 }
626 }
627 return false;
628 }
629
630 /**
631 * Generate an invoker method for the passed {@link LambdaForm}.
632 */
633 private byte[] generateCustomizedCodeBytes() {
634 classFilePrologue();
635
636 // Suppress this method in backtraces displayed to the user.
637 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
638
639 // Mark this method as a compiled LambdaForm
640 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
641
642 if (PROFILE_GWT && containsIntrinsic(MethodHandleImpl.Intrinsic.SELECT_ALTERNATIVE)) {
643 // For now, mark only GWT LambdaForms as @Shared.
644 // TODO: consider marking other non-customized LambdaForms as @Shared
645 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Shared;", true);
646 }
647
648 if (lambdaForm.forceInline) {
649 // Force inlining of this invoker method.
650 mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
651 } else {
652 mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
653 }
654
655 // iterate over the form's names, generating bytecode instructions for each
656 // start iterating at the first name following the arguments
657 Name onStack = null;
658 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
659 Name name = lambdaForm.names[i];
660
661 emitStoreResult(onStack);
662 onStack = name; // unless otherwise modified below
663 MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
664 switch (intr) {
665 case SELECT_ALTERNATIVE:
666 assert isSelectAlternative(i);
667 onStack = emitSelectAlternative(name, lambdaForm.names[i+1]);
668 i++; // skip MH.invokeBasic of the selectAlternative result
669 continue;
670 case GUARD_WITH_CATCH:
671 assert isGuardWithCatch(i);
672 onStack = emitGuardWithCatch(i);
673 i = i+2; // Jump to the end of GWC idiom
674 continue;
|
39 import sun.invoke.util.VerifyAccess;
40 import sun.invoke.util.VerifyType;
41 import sun.invoke.util.Wrapper;
42 import sun.reflect.misc.ReflectUtil;
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 MH_SIG = "L" + MH + ";";
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 LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
64 private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
65
66 /** Name of its super class*/
67 private static final String superName = OBJ;
68
69 /** Name of new class */
70 private final String className;
71
72 /** Name of the source file (for stack trace printing). */
73 private final String sourceFile;
74
75 private final LambdaForm lambdaForm;
76 private final String invokerName;
77 private final MethodType invokerType;
78
79 /** Info about local variables in compiled lambda form */
80 private final int[] localsMap; // index
81 private final BasicType[] localTypes; // basic type
82 private final Class<?>[] localClasses; // type
83
612
613 /**
614 * Generate customized bytecode for a given LambdaForm.
615 */
616 static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
617 InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
618 return g.loadMethod(g.generateCustomizedCodeBytes());
619 }
620
621 /** Determines whether a LambdaForm being compiled contains an intrinsic of some particular type. */
622 private boolean containsIntrinsic(MethodHandleImpl.Intrinsic intr) {
623 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
624 Name name = lambdaForm.names[i];
625 if (name.function.intrinsicName() == intr) {
626 return true;
627 }
628 }
629 return false;
630 }
631
632 /** Generates code to check that actual receiver and LambdaForm matches */
633 private boolean checkActualReceiver() {
634 // Expects MethodHandle on the stack and actual receiver MethodHandle in slot #0
635 mv.visitInsn(Opcodes.DUP);
636 mv.visitVarInsn(Opcodes.ALOAD, localsMap[0]);
637 mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "assertSame", LLV_SIG, false);
638 return true;
639 }
640
641 /**
642 * Generate an invoker method for the passed {@link LambdaForm}.
643 */
644 private byte[] generateCustomizedCodeBytes() {
645 classFilePrologue();
646
647 // Suppress this method in backtraces displayed to the user.
648 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
649
650 // Mark this method as a compiled LambdaForm
651 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
652
653 if (PROFILE_GWT && containsIntrinsic(MethodHandleImpl.Intrinsic.SELECT_ALTERNATIVE)) {
654 // For now, mark only GWT LambdaForms as @Shared.
655 // TODO: consider marking other non-customized LambdaForms as @Shared
656 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Shared;", true);
657 }
658
659 if (lambdaForm.forceInline) {
660 // Force inlining of this invoker method.
661 mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
662 } else {
663 mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
664 }
665
666 if (lambdaForm.customized != null) {
667 // Since LambdaForm is customized for a particular MethodHandle, it's safe to substitute
668 // receiver MethodHandle (at slot #0) with an embedded constant and use it instead.
669 // It enables more efficient code generation in some situations, since embedded constants
670 // are compile-time constants for JIT compiler.
671 mv.visitLdcInsn(constantPlaceholder(lambdaForm.customized));
672 mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
673 assert(checkActualReceiver()); // expects MethodHandle on top of the stack
674 mv.visitVarInsn(Opcodes.ASTORE, localsMap[0]);
675 }
676
677 // iterate over the form's names, generating bytecode instructions for each
678 // start iterating at the first name following the arguments
679 Name onStack = null;
680 for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
681 Name name = lambdaForm.names[i];
682
683 emitStoreResult(onStack);
684 onStack = name; // unless otherwise modified below
685 MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
686 switch (intr) {
687 case SELECT_ALTERNATIVE:
688 assert isSelectAlternative(i);
689 onStack = emitSelectAlternative(name, lambdaForm.names[i+1]);
690 i++; // skip MH.invokeBasic of the selectAlternative result
691 continue;
692 case GUARD_WITH_CATCH:
693 assert isGuardWithCatch(i);
694 onStack = emitGuardWithCatch(i);
695 i = i+2; // Jump to the end of GWC idiom
696 continue;
|