66 */
67 private static final class Transform extends SoftReference<LambdaForm> {
68 final long packedBytes;
69 final byte[] fullBytes;
70
71 // maybe add more for guard with test, catch exception, pointwise type conversions
72 private static final byte
73 BIND_ARG = 1,
74 ADD_ARG = 2,
75 DUP_ARG = 3,
76 SPREAD_ARGS = 4,
77 FILTER_ARG = 5,
78 FILTER_RETURN = 6,
79 FILTER_RETURN_TO_ZERO = 7,
80 COLLECT_ARGS = 8,
81 COLLECT_ARGS_TO_VOID = 9,
82 COLLECT_ARGS_TO_ARRAY = 10,
83 FOLD_ARGS = 11,
84 FOLD_ARGS_TO_VOID = 12,
85 PERMUTE_ARGS = 13,
86 LOCAL_TYPES = 14;
87
88 private static final boolean STRESS_TEST = false; // turn on to disable most packing
89 private static final int
90 PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4),
91 PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1,
92 PACKED_BYTE_MAX_LENGTH = (STRESS_TEST ? 3 : 64 / PACKED_BYTE_SIZE);
93
94 private static long packedBytes(byte[] bytes) {
95 if (bytes.length > PACKED_BYTE_MAX_LENGTH) return 0;
96 long pb = 0;
97 int bitset = 0;
98 for (int i = 0; i < bytes.length; i++) {
99 int b = bytes[i] & 0xFF;
100 bitset |= b;
101 pb |= (long)b << (i * PACKED_BYTE_SIZE);
102 }
103 if (!inRange(bitset))
104 return 0;
105 return pb;
106 }
678 Name callCombiner = new Name(combinerType, combinerArgs);
679
680 // insert the two new expressions
681 int exprPos = lambdaForm.arity();
682 buf.insertExpression(exprPos+0, getCombiner);
683 buf.insertExpression(exprPos+1, callCombiner);
684
685 // insert new arguments, if needed
686 int argPos = pos + resultArity; // skip result parameter
687 for (Name newParam : newParams) {
688 buf.insertParameter(argPos++, newParam);
689 }
690 assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length);
691 if (!dropResult) {
692 buf.replaceParameterByCopy(pos, exprPos+1+newParams.length);
693 }
694
695 return buf.endEdit();
696 }
697
698 LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
699 byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN);
700 Transform key = Transform.of(kind, newType.ordinal());
701 LambdaForm form = getInCache(key);
702 if (form != null) {
703 assert(form.arity == lambdaForm.arity);
704 assert(form.returnType() == newType);
705 return form;
706 }
707 LambdaFormBuffer buf = buffer();
708 buf.startEdit();
709
710 int insPos = lambdaForm.names.length;
711 Name callFilter;
712 if (constantZero) {
713 // Synthesize a constant zero value for the given type.
714 if (newType == V_TYPE)
715 callFilter = null;
716 else
717 callFilter = new Name(constantZero(newType));
739 }
740
741 if (callFilter != null)
742 buf.insertExpression(insPos++, callFilter);
743 buf.setResult(callFilter);
744
745 form = buf.endEdit();
746 return putInCache(key, form);
747 }
748
749 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
750 int combinerArity = combinerType.parameterCount();
751 byte kind = (dropResult ? Transform.FOLD_ARGS_TO_VOID : Transform.FOLD_ARGS);
752 Transform key = Transform.of(kind, foldPos, combinerArity);
753 LambdaForm form = getInCache(key);
754 if (form != null) {
755 assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_ARGS ? 1 : 0));
756 return form;
757 }
758 form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
759 return putInCache(key, form);
760 }
761
762 LambdaForm permuteArgumentsForm(int skip, int[] reorder) {
763 assert(skip == 1); // skip only the leading MH argument, names[0]
764 int length = lambdaForm.names.length;
765 int outArgs = reorder.length;
766 int inTypes = 0;
767 boolean nullPerm = true;
768 for (int i = 0; i < reorder.length; i++) {
769 int inArg = reorder[i];
770 if (inArg != i) nullPerm = false;
771 inTypes = Math.max(inTypes, inArg+1);
772 }
773 assert(skip + reorder.length == lambdaForm.arity);
774 if (nullPerm) return lambdaForm; // do not bother to cache
775 Transform key = Transform.of(Transform.PERMUTE_ARGS, reorder);
776 LambdaForm form = getInCache(key);
777 if (form != null) {
778 assert(form.arity == skip+inTypes) : form;
|
66 */
67 private static final class Transform extends SoftReference<LambdaForm> {
68 final long packedBytes;
69 final byte[] fullBytes;
70
71 // maybe add more for guard with test, catch exception, pointwise type conversions
72 private static final byte
73 BIND_ARG = 1,
74 ADD_ARG = 2,
75 DUP_ARG = 3,
76 SPREAD_ARGS = 4,
77 FILTER_ARG = 5,
78 FILTER_RETURN = 6,
79 FILTER_RETURN_TO_ZERO = 7,
80 COLLECT_ARGS = 8,
81 COLLECT_ARGS_TO_VOID = 9,
82 COLLECT_ARGS_TO_ARRAY = 10,
83 FOLD_ARGS = 11,
84 FOLD_ARGS_TO_VOID = 12,
85 PERMUTE_ARGS = 13,
86 LOCAL_TYPES = 14,
87 FOLD_SELECT_ARGS = 15,
88 FOLD_SELECT_ARGS_TO_VOID = 16;
89
90 private static final boolean STRESS_TEST = false; // turn on to disable most packing
91 private static final int
92 PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4),
93 PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1,
94 PACKED_BYTE_MAX_LENGTH = (STRESS_TEST ? 3 : 64 / PACKED_BYTE_SIZE);
95
96 private static long packedBytes(byte[] bytes) {
97 if (bytes.length > PACKED_BYTE_MAX_LENGTH) return 0;
98 long pb = 0;
99 int bitset = 0;
100 for (int i = 0; i < bytes.length; i++) {
101 int b = bytes[i] & 0xFF;
102 bitset |= b;
103 pb |= (long)b << (i * PACKED_BYTE_SIZE);
104 }
105 if (!inRange(bitset))
106 return 0;
107 return pb;
108 }
680 Name callCombiner = new Name(combinerType, combinerArgs);
681
682 // insert the two new expressions
683 int exprPos = lambdaForm.arity();
684 buf.insertExpression(exprPos+0, getCombiner);
685 buf.insertExpression(exprPos+1, callCombiner);
686
687 // insert new arguments, if needed
688 int argPos = pos + resultArity; // skip result parameter
689 for (Name newParam : newParams) {
690 buf.insertParameter(argPos++, newParam);
691 }
692 assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length);
693 if (!dropResult) {
694 buf.replaceParameterByCopy(pos, exprPos+1+newParams.length);
695 }
696
697 return buf.endEdit();
698 }
699
700
701 private LambdaForm makeArgumentCombinationForm(int pos,
702 MethodType combinerType,
703 int[] argPositions,
704 boolean keepArguments,
705 boolean dropResult) {
706 LambdaFormBuffer buf = buffer();
707 buf.startEdit();
708 int combinerArity = combinerType.parameterCount();
709 assert(combinerArity == argPositions.length);
710
711 int resultArity = (dropResult ? 0 : 1);
712
713 assert(pos <= lambdaForm.arity);
714 assert(pos > 0); // cannot filter the MH arg itself
715 assert(combinerType == combinerType.basicType());
716 assert(combinerType.returnType() != void.class || dropResult);
717
718 BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
719 BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE);
720
721 // The newly created LF will run with a different BMH.
722 // Switch over any pre-existing BMH field references to the new BMH class.
723 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
724 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
725 Name newBaseAddress = oldBaseAddress.withConstraint(newData);
726 buf.renameParameter(0, newBaseAddress);
727
728 Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress);
729 Object[] combinerArgs = new Object[1 + combinerArity];
730 combinerArgs[0] = getCombiner;
731 Name[] newParams;
732 if (keepArguments) {
733 newParams = new Name[0];
734 for (int i = 0; i < combinerArity; i++) {
735 combinerArgs[i + 1] = lambdaForm.parameter(1 + argPositions[i]);
736 assert (basicType(combinerType.parameterType(i)) == lambdaForm.parameterType(1 + argPositions[i]));
737 }
738 } else {
739 newParams = new Name[combinerArity];
740 for (int i = 0; i < newParams.length; i++) {
741 newParams[i] = lambdaForm.parameter(1 + argPositions[i]);
742 assert (basicType(combinerType.parameterType(i)) == lambdaForm.parameterType(1 + argPositions[i]));
743 }
744 System.arraycopy(newParams, 0,
745 combinerArgs, 1, combinerArity);
746 }
747 Name callCombiner = new Name(combinerType, combinerArgs);
748
749 // insert the two new expressions
750 int exprPos = lambdaForm.arity();
751 buf.insertExpression(exprPos+0, getCombiner);
752 buf.insertExpression(exprPos+1, callCombiner);
753
754 // insert new arguments, if needed
755 int argPos = pos + resultArity; // skip result parameter
756 for (Name newParam : newParams) {
757 buf.insertParameter(argPos++, newParam);
758 }
759 assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length);
760 if (!dropResult) {
761 buf.replaceParameterByCopy(pos, exprPos+1+newParams.length);
762 }
763
764 return buf.endEdit();
765 }
766
767 LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
768 byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN);
769 Transform key = Transform.of(kind, newType.ordinal());
770 LambdaForm form = getInCache(key);
771 if (form != null) {
772 assert(form.arity == lambdaForm.arity);
773 assert(form.returnType() == newType);
774 return form;
775 }
776 LambdaFormBuffer buf = buffer();
777 buf.startEdit();
778
779 int insPos = lambdaForm.names.length;
780 Name callFilter;
781 if (constantZero) {
782 // Synthesize a constant zero value for the given type.
783 if (newType == V_TYPE)
784 callFilter = null;
785 else
786 callFilter = new Name(constantZero(newType));
808 }
809
810 if (callFilter != null)
811 buf.insertExpression(insPos++, callFilter);
812 buf.setResult(callFilter);
813
814 form = buf.endEdit();
815 return putInCache(key, form);
816 }
817
818 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
819 int combinerArity = combinerType.parameterCount();
820 byte kind = (dropResult ? Transform.FOLD_ARGS_TO_VOID : Transform.FOLD_ARGS);
821 Transform key = Transform.of(kind, foldPos, combinerArity);
822 LambdaForm form = getInCache(key);
823 if (form != null) {
824 assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_ARGS ? 1 : 0));
825 return form;
826 }
827 form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
828 return putInCache(key, form);
829 }
830
831 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType, int ... argPositions) {
832 byte kind = (dropResult ? Transform.FOLD_SELECT_ARGS_TO_VOID
833 : Transform.FOLD_SELECT_ARGS);
834 int[] keyArgs = Arrays.copyOf(argPositions, argPositions.length + 1);
835 keyArgs[argPositions.length] = foldPos;
836 Transform key = Transform.of(kind, keyArgs);
837 LambdaForm form = getInCache(key);
838 if (form != null) {
839 assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_SELECT_ARGS ? 1 : 0));
840 return form;
841 }
842 form = makeArgumentCombinationForm(foldPos, combinerType, argPositions, true, dropResult);
843 return putInCache(key, form);
844 }
845
846 LambdaForm permuteArgumentsForm(int skip, int[] reorder) {
847 assert(skip == 1); // skip only the leading MH argument, names[0]
848 int length = lambdaForm.names.length;
849 int outArgs = reorder.length;
850 int inTypes = 0;
851 boolean nullPerm = true;
852 for (int i = 0; i < reorder.length; i++) {
853 int inArg = reorder[i];
854 if (inArg != i) nullPerm = false;
855 inTypes = Math.max(inTypes, inArg+1);
856 }
857 assert(skip + reorder.length == lambdaForm.arity);
858 if (nullPerm) return lambdaForm; // do not bother to cache
859 Transform key = Transform.of(Transform.PERMUTE_ARGS, reorder);
860 LambdaForm form = getInCache(key);
861 if (form != null) {
862 assert(form.arity == skip+inTypes) : form;
|