623 inputArgPos += chunk;
624 chunk = targetArgs.length - targetArgPos; // all the rest
625 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
626 assert(inputArgPos + chunk == collectNamePos); // use of rest of input args also
627 names[targetNamePos] = new Name(target, (Object[]) targetArgs);
628
629 LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
630 return SimpleMethodHandle.make(srcType, form);
631 }
632
633 @LambdaForm.Hidden
634 static
635 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
636 return testResult ? target : fallback;
637 }
638
639 static
640 MethodHandle makeGuardWithTest(MethodHandle test,
641 MethodHandle target,
642 MethodHandle fallback) {
643 MethodType basicType = target.type().basicType();
644 MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
645 int arity = basicType.parameterCount();
646 int extraNames = 3;
647 MethodType lambdaType = basicType.invokerType();
648 Name[] names = arguments(extraNames, lambdaType);
649
650 Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
651 Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
652
653 // call test
654 names[arity + 1] = new Name(test, testArgs);
655
656 // call selectAlternative
657 Object[] selectArgs = { names[arity + 1], target, fallback };
658 names[arity + 2] = new Name(Lazy.MH_selectAlternative, selectArgs);
659 targetArgs[0] = names[arity + 2];
660
661 // call target or fallback
662 names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
663
664 LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
665 return SimpleMethodHandle.make(target.type(), form);
666 }
667
668 /**
669 * The LambaForm shape for catchException combinator is the following:
670 * <blockquote><pre>{@code
671 * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
672 * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
673 * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
674 * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
675 * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
676 * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
677 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
678 * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
679 * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
680 * }</pre></blockquote>
681 *
682 * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
683 * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
684 * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
685 *
|
623 inputArgPos += chunk;
624 chunk = targetArgs.length - targetArgPos; // all the rest
625 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
626 assert(inputArgPos + chunk == collectNamePos); // use of rest of input args also
627 names[targetNamePos] = new Name(target, (Object[]) targetArgs);
628
629 LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
630 return SimpleMethodHandle.make(srcType, form);
631 }
632
633 @LambdaForm.Hidden
634 static
635 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
636 return testResult ? target : fallback;
637 }
638
639 static
640 MethodHandle makeGuardWithTest(MethodHandle test,
641 MethodHandle target,
642 MethodHandle fallback) {
643 MethodType type = target.type();
644 assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
645 MethodType basicType = type.basicType();
646 LambdaForm form = makeGuardWithTestForm(basicType);
647 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
648 BoundMethodHandle mh;
649 try {
650 mh = (BoundMethodHandle)
651 data.constructor().invokeBasic(type, form,
652 (Object) test, (Object) target, (Object) fallback);
653 } catch (Throwable ex) {
654 throw uncaughtException(ex);
655 }
656 assert(mh.type() == type);
657 return mh;
658 }
659
660 static
661 LambdaForm makeGuardWithTestForm(MethodType basicType) {
662 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
663 if (lform != null) return lform;
664 final int THIS_MH = 0; // the BMH_LLL
665 final int ARG_BASE = 1; // start of incoming arguments
666 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
667 int nameCursor = ARG_LIMIT;
668 final int GET_TEST = nameCursor++;
669 final int GET_TARGET = nameCursor++;
670 final int GET_FALLBACK = nameCursor++;
671 final int CALL_TEST = nameCursor++;
672 final int SELECT_ALT = nameCursor++;
673 final int CALL_TARGET = nameCursor++;
674 assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative
675
676 MethodType lambdaType = basicType.invokerType();
677 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
678
679 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
680 names[THIS_MH] = names[THIS_MH].withConstraint(data);
681 names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]);
682 names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]);
683 names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]);
684
685 Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class);
686
687 // call test
688 MethodType testType = basicType.changeReturnType(boolean.class).basicType();
689 invokeArgs[0] = names[GET_TEST];
690 names[CALL_TEST] = new Name(testType, invokeArgs);
691
692 // call selectAlternative
693 names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST],
694 names[GET_TARGET], names[GET_FALLBACK]);
695
696 // call target or fallback
697 invokeArgs[0] = names[SELECT_ALT];
698 names[CALL_TARGET] = new Name(basicType, invokeArgs);
699
700 lform = new LambdaForm("guard", lambdaType.parameterCount(), names);
701
702 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform);
703 }
704
705 /**
706 * The LambaForm shape for catchException combinator is the following:
707 * <blockquote><pre>{@code
708 * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
709 * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
710 * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
711 * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
712 * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
713 * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
714 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
715 * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
716 * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
717 * }</pre></blockquote>
718 *
719 * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
720 * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
721 * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
722 *
|