690 LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
691 return SimpleMethodHandle.make(srcType, form);
692 }
693
694 @LambdaForm.Hidden
695 static
696 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
697 return testResult ? target : fallback;
698 }
699
700 static
701 MethodHandle makeGuardWithTest(MethodHandle test,
702 MethodHandle target,
703 MethodHandle fallback) {
704 MethodType type = target.type();
705 assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
706 MethodType basicType = type.basicType();
707 LambdaForm form = makeGuardWithTestForm(basicType);
708 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
709 BoundMethodHandle mh;
710 try {
711 mh = (BoundMethodHandle)
712 data.constructor().invokeBasic(type, form,
713 (Object) test, (Object) target, (Object) fallback);
714 } catch (Throwable ex) {
715 throw uncaughtException(ex);
716 }
717 assert(mh.type() == type);
718 return mh;
719 }
720
721 static
722 LambdaForm makeGuardWithTestForm(MethodType basicType) {
723 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
724 if (lform != null) return lform;
725 final int THIS_MH = 0; // the BMH_LLL
726 final int ARG_BASE = 1; // start of incoming arguments
727 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
728 int nameCursor = ARG_LIMIT;
729 final int GET_TEST = nameCursor++;
730 final int GET_TARGET = nameCursor++;
731 final int GET_FALLBACK = nameCursor++;
732 final int CALL_TEST = nameCursor++;
733 final int SELECT_ALT = nameCursor++;
734 final int CALL_TARGET = nameCursor++;
735 assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative
736
737 MethodType lambdaType = basicType.invokerType();
738 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
739
740 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
|
690 LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
691 return SimpleMethodHandle.make(srcType, form);
692 }
693
694 @LambdaForm.Hidden
695 static
696 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
697 return testResult ? target : fallback;
698 }
699
700 static
701 MethodHandle makeGuardWithTest(MethodHandle test,
702 MethodHandle target,
703 MethodHandle fallback) {
704 MethodType type = target.type();
705 assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
706 MethodType basicType = type.basicType();
707 LambdaForm form = makeGuardWithTestForm(basicType);
708 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
709 BoundMethodHandle mh;
710
711 try {
712 mh = (BoundMethodHandle)
713 data.constructor().invokeBasic(type, form,
714 (Object) test, (Object) profile(target), (Object) profile(fallback));
715 } catch (Throwable ex) {
716 throw uncaughtException(ex);
717 }
718 assert(mh.type() == type);
719 return mh;
720 }
721
722
723 static
724 MethodHandle profile(MethodHandle target) {
725 if (DONT_INLINE_THRESHOLD > 0) {
726 return BlockInliningWrapper.make(target);
727 } else {
728 return target;
729 }
730 }
731
732 /**
733 * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times.
734 * Corresponding LambdaForm has @DontInline when compiled into bytecode.
735 */
736 static class BlockInliningWrapper extends DelegatingMethodHandle {
737 private final MethodHandle target;
738 private int count;
739 private volatile boolean isActivated = true;
740
741 private BlockInliningWrapper(MethodHandle target, LambdaForm lform, int count) {
742 super(target.type(), lform);
743 this.target = target;
744 this.count = count;
745 }
746
747 @Hidden
748 @Override
749 protected MethodHandle getTarget() {
750 return target;
751 }
752
753 @Override
754 public MethodHandle asTypeUncached(MethodType newType) {
755 MethodHandle newTarget = target.asType(newType);
756 return asTypeCache = isActivated ? make(newTarget)
757 : newTarget; // no need for a wrapper anymore
758 }
759
760 boolean unblock() {
761 if (count <= 0) {
762 // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
763 if (isActivated) {
764 isActivated = false;
765 return true;
766 } else {
767 return false;
768 }
769 } else {
770 --count;
771 return false;
772 }
773 }
774
775 static MethodHandle make(MethodHandle target) {
776 LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(target,
777 MethodTypeForm.LF_DELEGATE_COUNTING, BlockInliningWrapper.class, "reinvoker.dontInline", false,
778 DelegatingMethodHandle.NF_getTarget, NF_maybeUnblock);
779 MethodHandle wrapper = new BlockInliningWrapper(target, lform, DONT_INLINE_THRESHOLD);
780 return wrapper;
781 }
782
783 @Hidden
784 static void maybeUnblock(Object o1) {
785 BlockInliningWrapper wrapper = (BlockInliningWrapper) o1;
786 if (wrapper.unblock()) {
787 // Reached invocation threshold. Replace counting/blocking wrapper with a reinvoker.
788 wrapper.isActivated = false;
789 MethodHandle target = wrapper.getTarget();
790 LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(
791 target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
792 wrapper.updateForm(lform);
793 }
794 }
795
796 static final NamedFunction NF_maybeUnblock;
797 static {
798 Class<?> THIS_CLASS = BlockInliningWrapper.class;
799 try {
800 NF_maybeUnblock = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeUnblock", Object.class));
801 } catch (ReflectiveOperationException ex) {
802 throw newInternalError(ex);
803 }
804 }
805 }
806
807 static
808 LambdaForm makeGuardWithTestForm(MethodType basicType) {
809 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
810 if (lform != null) return lform;
811 final int THIS_MH = 0; // the BMH_LLL
812 final int ARG_BASE = 1; // start of incoming arguments
813 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
814 int nameCursor = ARG_LIMIT;
815 final int GET_TEST = nameCursor++;
816 final int GET_TARGET = nameCursor++;
817 final int GET_FALLBACK = nameCursor++;
818 final int CALL_TEST = nameCursor++;
819 final int SELECT_ALT = nameCursor++;
820 final int CALL_TARGET = nameCursor++;
821 assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative
822
823 MethodType lambdaType = basicType.invokerType();
824 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
825
826 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
|