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


 599         mv.visitInsn(opcode);
 600     }
 601 
 602     private static String getInternalName(Class<?> c) {
 603         if (c == Object.class)             return OBJ;
 604         else if (c == Object[].class)      return OBJARY;
 605         else if (c == Class.class)         return CLS;
 606         else if (c == MethodHandle.class)  return MH;
 607         assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName();
 608         return c.getName().replace('.', '/');
 609     }
 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     /**
 620      * Generate an invoker method for the passed {@link LambdaForm}.
 621      */
 622     private byte[] generateCustomizedCodeBytes() {
 623         classFilePrologue();
 624 
 625         // Suppress this method in backtraces displayed to the user.
 626         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 627 
 628         // Mark this method as a compiled LambdaForm
 629         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
 630 






 631         if (lambdaForm.forceInline) {
 632             // Force inlining of this invoker method.
 633             mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
 634         } else {
 635             mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
 636         }
 637 
 638 
 639         // iterate over the form's names, generating bytecode instructions for each
 640         // start iterating at the first name following the arguments
 641         Name onStack = null;
 642         for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
 643             Name name = lambdaForm.names[i];
 644 
 645             emitStoreResult(onStack);
 646             onStack = name;  // unless otherwise modified below
 647             MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
 648             switch (intr) {
 649                 case SELECT_ALTERNATIVE:
 650                     assert isSelectAlternative(i);
 651                     onStack = emitSelectAlternative(name, lambdaForm.names[i+1]);
 652                     i++;  // skip MH.invokeBasic of the selectAlternative result
 653                     continue;
 654                 case GUARD_WITH_CATCH:
 655                     assert isGuardWithCatch(i);
 656                     onStack = emitGuardWithCatch(i);
 657                     i = i+2; // Jump to the end of GWC idiom
 658                     continue;


 988      *
 989      * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest):
 990      * <blockquote><pre>{@code
 991      *   Lambda(a0:L,a1:I)=>{
 992      *     t2:I=foo.test(a1:I);
 993      *     t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
 994      *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
 995      * }</pre></blockquote>
 996      */
 997     private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
 998         assert isStaticallyInvocable(invokeBasicName);
 999 
1000         Name receiver = (Name) invokeBasicName.arguments[0];
1001 
1002         Label L_fallback = new Label();
1003         Label L_done     = new Label();
1004 
1005         // load test result
1006         emitPushArgument(selectAlternativeName, 0);
1007 





1008         // if_icmpne L_fallback
1009         mv.visitJumpInsn(Opcodes.IFEQ, L_fallback);
1010 
1011         // invoke selectAlternativeName.arguments[1]
1012         Class<?>[] preForkClasses = localClasses.clone();
1013         emitPushArgument(selectAlternativeName, 1);  // get 2nd argument of selectAlternative
1014         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
1015         emitStaticInvoke(invokeBasicName);
1016 
1017         // goto L_done
1018         mv.visitJumpInsn(Opcodes.GOTO, L_done);
1019 
1020         // L_fallback:
1021         mv.visitLabel(L_fallback);
1022 
1023         // invoke selectAlternativeName.arguments[2]
1024         System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
1025         emitPushArgument(selectAlternativeName, 2);  // get 3rd argument of selectAlternative
1026         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
1027         emitStaticInvoke(invokeBasicName);




 599         mv.visitInsn(opcode);
 600     }
 601 
 602     private static String getInternalName(Class<?> c) {
 603         if (c == Object.class)             return OBJ;
 604         else if (c == Object[].class)      return OBJARY;
 605         else if (c == Class.class)         return CLS;
 606         else if (c == MethodHandle.class)  return MH;
 607         assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName();
 608         return c.getName().replace('.', '/');
 609     }
 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;


1004      *
1005      * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest):
1006      * <blockquote><pre>{@code
1007      *   Lambda(a0:L,a1:I)=>{
1008      *     t2:I=foo.test(a1:I);
1009      *     t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
1010      *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
1011      * }</pre></blockquote>
1012      */
1013     private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
1014         assert isStaticallyInvocable(invokeBasicName);
1015 
1016         Name receiver = (Name) invokeBasicName.arguments[0];
1017 
1018         Label L_fallback = new Label();
1019         Label L_done     = new Label();
1020 
1021         // load test result
1022         emitPushArgument(selectAlternativeName, 0);
1023 
1024         if (PROFILE_GWT) {
1025             emitPushArgument(selectAlternativeName, 3);
1026             mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "profileBranch", "(Z[I)Z", false);
1027         }
1028 
1029         // if_icmpne L_fallback
1030         mv.visitJumpInsn(Opcodes.IFEQ, L_fallback);
1031 
1032         // invoke selectAlternativeName.arguments[1]
1033         Class<?>[] preForkClasses = localClasses.clone();
1034         emitPushArgument(selectAlternativeName, 1);  // get 2nd argument of selectAlternative
1035         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
1036         emitStaticInvoke(invokeBasicName);
1037 
1038         // goto L_done
1039         mv.visitJumpInsn(Opcodes.GOTO, L_done);
1040 
1041         // L_fallback:
1042         mv.visitLabel(L_fallback);
1043 
1044         // invoke selectAlternativeName.arguments[2]
1045         System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
1046         emitPushArgument(selectAlternativeName, 2);  // get 3rd argument of selectAlternative
1047         emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
1048         emitStaticInvoke(invokeBasicName);


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