604
605 Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
606 Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
607
608 // call test
609 names[arity + 1] = new Name(test, testArgs);
610
611 // call selectAlternative
612 Object[] selectArgs = { names[arity + 1], target, fallback };
613 names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
614 targetArgs[0] = names[arity + 2];
615
616 // call target or fallback
617 names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
618
619 LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
620 return SimpleMethodHandle.make(target.type(), form);
621 }
622
623 /**
624 * The LambaForm shape for catchException combinator is the following:
625 * <blockquote><pre>{@code
626 * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
627 * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
628 * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
629 * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
630 * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
631 * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
632 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
633 * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
634 * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
635 * }</pre></blockquote>
636 *
637 * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
638 * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
639 * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
640 *
641 * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
642 * among catchException combinators with the same basic type.
643 */
644 private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
685 Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
686 names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs);
687
688 // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
689 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
690 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
691 names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
692
693 lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
694
695 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
696 }
697
698 static
699 MethodHandle makeGuardWithCatch(MethodHandle target,
700 Class<? extends Throwable> exType,
701 MethodHandle catcher) {
702 MethodType type = target.type();
703 LambdaForm form = makeGuardWithCatchForm(type.basicType());
704
705 // Prepare auxiliary method handles used during LambdaForm interpreation.
706 // Box arguments and wrap them into Object[]: ValueConversions.array().
707 MethodType varargsType = type.changeReturnType(Object[].class);
708 MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
709 .asType(varargsType);
710 // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
711 MethodHandle unboxResult;
712 if (type.returnType().isPrimitive()) {
713 unboxResult = ValueConversions.unbox(type.returnType());
714 } else {
715 unboxResult = ValueConversions.identity();
716 }
717
718 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
719 BoundMethodHandle mh;
720 try {
721 mh = (BoundMethodHandle)
722 data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
723 (Object) collectArgs, (Object) unboxResult);
724 } catch (Throwable ex) {
725 throw uncaughtException(ex);
|
604
605 Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
606 Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
607
608 // call test
609 names[arity + 1] = new Name(test, testArgs);
610
611 // call selectAlternative
612 Object[] selectArgs = { names[arity + 1], target, fallback };
613 names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
614 targetArgs[0] = names[arity + 2];
615
616 // call target or fallback
617 names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
618
619 LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
620 return SimpleMethodHandle.make(target.type(), form);
621 }
622
623 /**
624 * The LambdaForm shape for catchException combinator is the following:
625 * <blockquote><pre>{@code
626 * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
627 * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
628 * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
629 * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
630 * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
631 * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
632 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
633 * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
634 * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
635 * }</pre></blockquote>
636 *
637 * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
638 * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
639 * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
640 *
641 * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
642 * among catchException combinators with the same basic type.
643 */
644 private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
685 Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
686 names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs);
687
688 // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
689 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
690 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
691 names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
692
693 lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
694
695 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
696 }
697
698 static
699 MethodHandle makeGuardWithCatch(MethodHandle target,
700 Class<? extends Throwable> exType,
701 MethodHandle catcher) {
702 MethodType type = target.type();
703 LambdaForm form = makeGuardWithCatchForm(type.basicType());
704
705 // Prepare auxiliary method handles used during LambdaForm interpretation.
706 // Box arguments and wrap them into Object[]: ValueConversions.array().
707 MethodType varargsType = type.changeReturnType(Object[].class);
708 MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
709 .asType(varargsType);
710 // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
711 MethodHandle unboxResult;
712 if (type.returnType().isPrimitive()) {
713 unboxResult = ValueConversions.unbox(type.returnType());
714 } else {
715 unboxResult = ValueConversions.identity();
716 }
717
718 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
719 BoundMethodHandle mh;
720 try {
721 mh = (BoundMethodHandle)
722 data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
723 (Object) collectArgs, (Object) unboxResult);
724 } catch (Throwable ex) {
725 throw uncaughtException(ex);
|