58 // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version. |
58 // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version. |
59 return new LambdaFormEditor(lambdaForm.uncustomize()); |
59 return new LambdaFormEditor(lambdaForm.uncustomize()); |
60 } |
60 } |
61 |
61 |
62 /** A description of a cached transform, possibly associated with the result of the transform. |
62 /** A description of a cached transform, possibly associated with the result of the transform. |
63 * The logical content is a sequence of byte values, starting with a Kind.ordinal value. |
63 * The logical content is a sequence of byte values, starting with a kind value. |
64 * The sequence is unterminated, ending with an indefinite number of zero bytes. |
64 * The sequence is unterminated, ending with an indefinite number of zero bytes. |
65 * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long. |
65 * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long. |
66 */ |
66 */ |
67 private static final class Transform extends SoftReference<LambdaForm> { |
67 private static final class Transform extends SoftReference<LambdaForm> { |
68 final long packedBytes; |
68 final long packedBytes; |
69 final byte[] fullBytes; |
69 final byte[] fullBytes; |
70 |
70 |
71 private enum Kind { |
71 // maybe add more for guard with test, catch exception, pointwise type conversions |
72 NO_KIND, // necessary because ordinal must be greater than zero |
72 private static final byte |
73 BIND_ARG, ADD_ARG, DUP_ARG, |
73 BIND_ARG = 1, |
74 SPREAD_ARGS, |
74 ADD_ARG = 2, |
75 FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO, |
75 DUP_ARG = 3, |
76 COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY, |
76 SPREAD_ARGS = 4, |
77 FOLD_ARGS, FOLD_ARGS_TO_VOID, |
77 FILTER_ARG = 5, |
78 PERMUTE_ARGS, |
78 FILTER_RETURN = 6, |
79 LOCAL_TYPES |
79 FILTER_RETURN_TO_ZERO = 7, |
80 //maybe add more for guard with test, catch exception, pointwise type conversions |
80 COLLECT_ARGS = 8, |
81 } |
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; |
82 |
87 |
83 private static final boolean STRESS_TEST = false; // turn on to disable most packing |
88 private static final boolean STRESS_TEST = false; // turn on to disable most packing |
84 private static final int |
89 private static final int |
85 PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4), |
90 PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4), |
86 PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1, |
91 PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1, |
160 |
151 |
161 private static byte bval(int b) { |
152 private static byte bval(int b) { |
162 assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte |
153 assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte |
163 return (byte)b; |
154 return (byte)b; |
164 } |
155 } |
165 private static byte bval(Kind k) { |
156 static Transform of(byte k, int b1) { |
166 return bval(k.ordinal()); |
|
167 } |
|
168 static Transform of(Kind k, int b1) { |
|
169 byte b0 = bval(k); |
157 byte b0 = bval(k); |
170 if (inRange(b0 | b1)) |
158 if (inRange(b0 | b1)) |
171 return new Transform(packedBytes(b0, b1)); |
159 return new Transform(packedBytes(b0, b1)); |
172 else |
160 else |
173 return new Transform(fullBytes(b0, b1)); |
161 return new Transform(fullBytes(b0, b1)); |
174 } |
162 } |
175 static Transform of(Kind k, int b1, int b2) { |
163 static Transform of(byte b0, int b1, int b2) { |
176 byte b0 = (byte) k.ordinal(); |
|
177 if (inRange(b0 | b1 | b2)) |
164 if (inRange(b0 | b1 | b2)) |
178 return new Transform(packedBytes(b0, b1, b2)); |
165 return new Transform(packedBytes(b0, b1, b2)); |
179 else |
166 else |
180 return new Transform(fullBytes(b0, b1, b2)); |
167 return new Transform(fullBytes(b0, b1, b2)); |
181 } |
168 } |
182 static Transform of(Kind k, int b1, int b2, int b3) { |
169 static Transform of(byte b0, int b1, int b2, int b3) { |
183 byte b0 = (byte) k.ordinal(); |
|
184 if (inRange(b0 | b1 | b2 | b3)) |
170 if (inRange(b0 | b1 | b2 | b3)) |
185 return new Transform(packedBytes(b0, b1, b2, b3)); |
171 return new Transform(packedBytes(b0, b1, b2, b3)); |
186 else |
172 else |
187 return new Transform(fullBytes(b0, b1, b2, b3)); |
173 return new Transform(fullBytes(b0, b1, b2, b3)); |
188 } |
174 } |
189 private static final byte[] NO_BYTES = {}; |
175 private static final byte[] NO_BYTES = {}; |
190 static Transform of(Kind k, int... b123) { |
176 static Transform of(byte kind, int... b123) { |
191 return ofBothArrays(k, b123, NO_BYTES); |
177 return ofBothArrays(kind, b123, NO_BYTES); |
192 } |
178 } |
193 static Transform of(Kind k, int b1, byte[] b234) { |
179 static Transform of(byte kind, int b1, byte[] b234) { |
194 return ofBothArrays(k, new int[]{ b1 }, b234); |
180 return ofBothArrays(kind, new int[]{ b1 }, b234); |
195 } |
181 } |
196 static Transform of(Kind k, int b1, int b2, byte[] b345) { |
182 static Transform of(byte kind, int b1, int b2, byte[] b345) { |
197 return ofBothArrays(k, new int[]{ b1, b2 }, b345); |
183 return ofBothArrays(kind, new int[]{ b1, b2 }, b345); |
198 } |
184 } |
199 private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) { |
185 private static Transform ofBothArrays(byte kind, int[] b123, byte[] b456) { |
200 byte[] fullBytes = new byte[1 + b123.length + b456.length]; |
186 byte[] fullBytes = new byte[1 + b123.length + b456.length]; |
201 int i = 0; |
187 int i = 0; |
202 fullBytes[i++] = bval(k); |
188 fullBytes[i++] = bval(kind); |
203 for (int bv : b123) { |
189 for (int bv : b123) { |
204 fullBytes[i++] = bval(bv); |
190 fullBytes[i++] = bval(bv); |
205 } |
191 } |
206 for (byte bv : b456) { |
192 for (byte bv : b456) { |
207 fullBytes[i++] = bv; |
193 fullBytes[i++] = bv; |
482 form = buf.endEdit(); |
468 form = buf.endEdit(); |
483 return putInCache(key, form); |
469 return putInCache(key, form); |
484 } |
470 } |
485 |
471 |
486 LambdaForm addArgumentForm(int pos, BasicType type) { |
472 LambdaForm addArgumentForm(int pos, BasicType type) { |
487 Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal()); |
473 Transform key = Transform.of(Transform.ADD_ARG, pos, type.ordinal()); |
488 LambdaForm form = getInCache(key); |
474 LambdaForm form = getInCache(key); |
489 if (form != null) { |
475 if (form != null) { |
490 assert(form.arity == lambdaForm.arity+1); |
476 assert(form.arity == lambdaForm.arity+1); |
491 assert(form.parameterType(pos) == type); |
477 assert(form.parameterType(pos) == type); |
492 return form; |
478 return form; |
567 boolean dropResult = (collectorType.returnType() == void.class); |
553 boolean dropResult = (collectorType.returnType() == void.class); |
568 if (collectorArity == 1 && !dropResult) { |
554 if (collectorArity == 1 && !dropResult) { |
569 return filterArgumentForm(pos, basicType(collectorType.parameterType(0))); |
555 return filterArgumentForm(pos, basicType(collectorType.parameterType(0))); |
570 } |
556 } |
571 byte[] newTypes = BasicType.basicTypesOrd(collectorType.parameterArray()); |
557 byte[] newTypes = BasicType.basicTypesOrd(collectorType.parameterArray()); |
572 Transform.Kind kind = (dropResult |
558 byte kind = (dropResult |
573 ? Transform.Kind.COLLECT_ARGS_TO_VOID |
559 ? Transform.COLLECT_ARGS_TO_VOID |
574 : Transform.Kind.COLLECT_ARGS); |
560 : Transform.COLLECT_ARGS); |
575 if (dropResult && collectorArity == 0) pos = 1; // pure side effect |
561 if (dropResult && collectorArity == 0) pos = 1; // pure side effect |
576 Transform key = Transform.of(kind, pos, collectorArity, newTypes); |
562 Transform key = Transform.of(kind, pos, collectorArity, newTypes); |
577 LambdaForm form = getInCache(key); |
563 LambdaForm form = getInCache(key); |
578 if (form != null) { |
564 if (form != null) { |
579 assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity); |
565 assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity); |
596 if (!elementType.isPrimitive()) |
582 if (!elementType.isPrimitive()) |
597 return null; |
583 return null; |
598 argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); |
584 argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); |
599 } |
585 } |
600 assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType))); |
586 assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType))); |
601 Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY; |
587 byte kind = Transform.COLLECT_ARGS_TO_ARRAY; |
602 Transform key = Transform.of(kind, pos, collectorArity, argTypeKey); |
588 Transform key = Transform.of(kind, pos, collectorArity, argTypeKey); |
603 LambdaForm form = getInCache(key); |
589 LambdaForm form = getInCache(key); |
604 if (form != null) { |
590 if (form != null) { |
605 assert(form.arity == lambdaForm.arity - 1 + collectorArity); |
591 assert(form.arity == lambdaForm.arity - 1 + collectorArity); |
606 return form; |
592 return form; |
632 form = buf.endEdit(); |
618 form = buf.endEdit(); |
633 return putInCache(key, form); |
619 return putInCache(key, form); |
634 } |
620 } |
635 |
621 |
636 LambdaForm filterArgumentForm(int pos, BasicType newType) { |
622 LambdaForm filterArgumentForm(int pos, BasicType newType) { |
637 Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal()); |
623 Transform key = Transform.of(Transform.FILTER_ARG, pos, newType.ordinal()); |
638 LambdaForm form = getInCache(key); |
624 LambdaForm form = getInCache(key); |
639 if (form != null) { |
625 if (form != null) { |
640 assert(form.arity == lambdaForm.arity); |
626 assert(form.arity == lambdaForm.arity); |
641 assert(form.parameterType(pos) == newType); |
627 assert(form.parameterType(pos) == newType); |
642 return form; |
628 return form; |
760 return putInCache(key, form); |
746 return putInCache(key, form); |
761 } |
747 } |
762 |
748 |
763 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) { |
749 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) { |
764 int combinerArity = combinerType.parameterCount(); |
750 int combinerArity = combinerType.parameterCount(); |
765 Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS); |
751 byte kind = (dropResult ? Transform.FOLD_ARGS_TO_VOID : Transform.FOLD_ARGS); |
766 Transform key = Transform.of(kind, foldPos, combinerArity); |
752 Transform key = Transform.of(kind, foldPos, combinerArity); |
767 LambdaForm form = getInCache(key); |
753 LambdaForm form = getInCache(key); |
768 if (form != null) { |
754 if (form != null) { |
769 assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0)); |
755 assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_ARGS ? 1 : 0)); |
770 return form; |
756 return form; |
771 } |
757 } |
772 form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult); |
758 form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult); |
773 return putInCache(key, form); |
759 return putInCache(key, form); |
774 } |
760 } |