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