src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

Print this page
rev 11254 : 8063137: Never-taken branches should be pruned when GWT LambdaForms are shared
Reviewed-by: ?
rev 11255 : [mq]: gwt.profile.1
rev 11258 : 8069591: Customize LambdaForms which are invoked using MH.invoke/invokeExact
Reviewed-by: ?


  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;


src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File