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 11011 : 8063137: Never-taken branches should be pruned when GWT LambdaForms are shared
Reviewed-by: ?


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




 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 (PROFILE_GWT && lambdaForm.isGWT) {
 632             mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$IgnoreProfile;", true);
 633         }
 634 
 635         if (lambdaForm.forceInline) {
 636             // Force inlining of this invoker method.
 637             mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
 638         } else {
 639             mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
 640         }
 641 

 642         // iterate over the form's names, generating bytecode instructions for each
 643         // start iterating at the first name following the arguments
 644         Name onStack = null;
 645         for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
 646             Name name = lambdaForm.names[i];
 647 
 648             emitStoreResult(onStack);
 649             onStack = name;  // unless otherwise modified below
 650             MethodHandleImpl.Intrinsic intr = name.function.intrinsicName();
 651             switch (intr) {
 652                 case SELECT_ALTERNATIVE:
 653                     assert isSelectAlternative(i);
 654                     onStack = emitSelectAlternative(name, lambdaForm.names[i+1]);
 655                     i++;  // skip MH.invokeBasic of the selectAlternative result
 656                     continue;
 657                 case GUARD_WITH_CATCH:
 658                     assert isGuardWithCatch(i);
 659                     onStack = emitGuardWithCatch(i);
 660                     i = i+2; // Jump to the end of GWC idiom
 661                     continue;


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