< prev index next >
src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
Print this page
rev 15320 : 8163370: Reduce number of classes loaded by common usage of java.lang.invoke
Reviewed-by: igerasim, psandoz
@@ -58,29 +58,34 @@
// It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version.
return new LambdaFormEditor(lambdaForm.uncustomize());
}
/** A description of a cached transform, possibly associated with the result of the transform.
- * The logical content is a sequence of byte values, starting with a Kind.ordinal value.
+ * The logical content is a sequence of byte values, starting with a kind value.
* The sequence is unterminated, ending with an indefinite number of zero bytes.
* Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
*/
private static final class Transform extends SoftReference<LambdaForm> {
final long packedBytes;
final byte[] fullBytes;
- private enum Kind {
- NO_KIND, // necessary because ordinal must be greater than zero
- BIND_ARG, ADD_ARG, DUP_ARG,
- SPREAD_ARGS,
- FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO,
- COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY,
- FOLD_ARGS, FOLD_ARGS_TO_VOID,
- PERMUTE_ARGS,
- LOCAL_TYPES
- //maybe add more for guard with test, catch exception, pointwise type conversions
- }
+ // maybe add more for guard with test, catch exception, pointwise type conversions
+ private static final byte
+ BIND_ARG = 1,
+ ADD_ARG = 2,
+ DUP_ARG = 3,
+ SPREAD_ARGS = 4,
+ FILTER_ARG = 5,
+ FILTER_RETURN = 6,
+ FILTER_RETURN_TO_ZERO = 7,
+ COLLECT_ARGS = 8,
+ COLLECT_ARGS_TO_VOID = 9,
+ COLLECT_ARGS_TO_ARRAY = 10,
+ FOLD_ARGS = 11,
+ FOLD_ARGS_TO_VOID = 12,
+ PERMUTE_ARGS = 13,
+ LOCAL_TYPES = 14;
private static final boolean STRESS_TEST = false; // turn on to disable most packing
private static final int
PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4),
PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1,
@@ -129,24 +134,10 @@
}
assert(packedBytes(bytes) == 0);
return bytes;
}
- private byte byteAt(int i) {
- long pb = packedBytes;
- if (pb == 0) {
- if (i >= fullBytes.length) return 0;
- return fullBytes[i];
- }
- assert(fullBytes == null);
- if (i > PACKED_BYTE_MAX_LENGTH) return 0;
- int pos = (i * PACKED_BYTE_SIZE);
- return (byte)((pb >>> pos) & PACKED_BYTE_MASK);
- }
-
- Kind kind() { return Kind.values()[byteAt(0)]; }
-
private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
super(result);
this.packedBytes = packedBytes;
this.fullBytes = fullBytes;
}
@@ -160,48 +151,43 @@
private static byte bval(int b) {
assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte
return (byte)b;
}
- private static byte bval(Kind k) {
- return bval(k.ordinal());
- }
- static Transform of(Kind k, int b1) {
+ static Transform of(byte k, int b1) {
byte b0 = bval(k);
if (inRange(b0 | b1))
return new Transform(packedBytes(b0, b1));
else
return new Transform(fullBytes(b0, b1));
}
- static Transform of(Kind k, int b1, int b2) {
- byte b0 = (byte) k.ordinal();
+ static Transform of(byte b0, int b1, int b2) {
if (inRange(b0 | b1 | b2))
return new Transform(packedBytes(b0, b1, b2));
else
return new Transform(fullBytes(b0, b1, b2));
}
- static Transform of(Kind k, int b1, int b2, int b3) {
- byte b0 = (byte) k.ordinal();
+ static Transform of(byte b0, int b1, int b2, int b3) {
if (inRange(b0 | b1 | b2 | b3))
return new Transform(packedBytes(b0, b1, b2, b3));
else
return new Transform(fullBytes(b0, b1, b2, b3));
}
private static final byte[] NO_BYTES = {};
- static Transform of(Kind k, int... b123) {
- return ofBothArrays(k, b123, NO_BYTES);
+ static Transform of(byte kind, int... b123) {
+ return ofBothArrays(kind, b123, NO_BYTES);
}
- static Transform of(Kind k, int b1, byte[] b234) {
- return ofBothArrays(k, new int[]{ b1 }, b234);
+ static Transform of(byte kind, int b1, byte[] b234) {
+ return ofBothArrays(kind, new int[]{ b1 }, b234);
}
- static Transform of(Kind k, int b1, int b2, byte[] b345) {
- return ofBothArrays(k, new int[]{ b1, b2 }, b345);
+ static Transform of(byte kind, int b1, int b2, byte[] b345) {
+ return ofBothArrays(kind, new int[]{ b1, b2 }, b345);
}
- private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) {
+ private static Transform ofBothArrays(byte kind, int[] b123, byte[] b456) {
byte[] fullBytes = new byte[1 + b123.length + b456.length];
int i = 0;
- fullBytes[i++] = bval(k);
+ fullBytes[i++] = bval(kind);
for (int bv : b123) {
fullBytes[i++] = bval(bv);
}
for (byte bv : b456) {
fullBytes[i++] = bv;
@@ -447,11 +433,11 @@
/// Editing methods for lambda forms.
// Each editing method can (potentially) cache the edited LF so that it can be reused later.
LambdaForm bindArgumentForm(int pos) {
- Transform key = Transform.of(Transform.Kind.BIND_ARG, pos);
+ Transform key = Transform.of(Transform.BIND_ARG, pos);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
return form;
}
@@ -482,11 +468,11 @@
form = buf.endEdit();
return putInCache(key, form);
}
LambdaForm addArgumentForm(int pos, BasicType type) {
- Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal());
+ Transform key = Transform.of(Transform.ADD_ARG, pos, type.ordinal());
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity+1);
assert(form.parameterType(pos) == type);
return form;
@@ -499,11 +485,11 @@
form = buf.endEdit();
return putInCache(key, form);
}
LambdaForm dupArgumentForm(int srcPos, int dstPos) {
- Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos);
+ Transform key = Transform.of(Transform.DUP_ARG, srcPos, dstPos);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity-1);
return form;
}
@@ -528,11 +514,11 @@
if (bt.basicTypeClass() != elementType) {
if (elementType.isPrimitive()) {
elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
}
}
- Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
+ Transform key = Transform.of(Transform.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity - arrayLength + 1);
return form;
}
@@ -567,13 +553,13 @@
boolean dropResult = (collectorType.returnType() == void.class);
if (collectorArity == 1 && !dropResult) {
return filterArgumentForm(pos, basicType(collectorType.parameterType(0)));
}
byte[] newTypes = BasicType.basicTypesOrd(collectorType.parameterArray());
- Transform.Kind kind = (dropResult
- ? Transform.Kind.COLLECT_ARGS_TO_VOID
- : Transform.Kind.COLLECT_ARGS);
+ byte kind = (dropResult
+ ? Transform.COLLECT_ARGS_TO_VOID
+ : Transform.COLLECT_ARGS);
if (dropResult && collectorArity == 0) pos = 1; // pure side effect
Transform key = Transform.of(kind, pos, collectorArity, newTypes);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity);
@@ -596,11 +582,11 @@
if (!elementType.isPrimitive())
return null;
argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
}
assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType)));
- Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY;
+ byte kind = Transform.COLLECT_ARGS_TO_ARRAY;
Transform key = Transform.of(kind, pos, collectorArity, argTypeKey);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity - 1 + collectorArity);
return form;
@@ -632,11 +618,11 @@
form = buf.endEdit();
return putInCache(key, form);
}
LambdaForm filterArgumentForm(int pos, BasicType newType) {
- Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal());
+ Transform key = Transform.of(Transform.FILTER_ARG, pos, newType.ordinal());
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity);
assert(form.parameterType(pos) == newType);
return form;
@@ -708,11 +694,11 @@
return buf.endEdit();
}
LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
- Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN);
+ byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN);
Transform key = Transform.of(kind, newType.ordinal());
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == lambdaForm.arity);
assert(form.returnType() == newType);
@@ -760,15 +746,15 @@
return putInCache(key, form);
}
LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
int combinerArity = combinerType.parameterCount();
- Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS);
+ byte kind = (dropResult ? Transform.FOLD_ARGS_TO_VOID : Transform.FOLD_ARGS);
Transform key = Transform.of(kind, foldPos, combinerArity);
LambdaForm form = getInCache(key);
if (form != null) {
- assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0));
+ assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_ARGS ? 1 : 0));
return form;
}
form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
return putInCache(key, form);
}
@@ -784,11 +770,11 @@
if (inArg != i) nullPerm = false;
inTypes = Math.max(inTypes, inArg+1);
}
assert(skip + reorder.length == lambdaForm.arity);
if (nullPerm) return lambdaForm; // do not bother to cache
- Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder);
+ Transform key = Transform.of(Transform.PERMUTE_ARGS, reorder);
LambdaForm form = getInCache(key);
if (form != null) {
assert(form.arity == skip+inTypes) : form;
return form;
}
@@ -853,11 +839,11 @@
LambdaForm noteLoopLocalTypesForm(int pos, BasicType[] localTypes) {
assert(lambdaForm.isLoop(pos));
int[] desc = BasicType.basicTypeOrds(localTypes);
desc = Arrays.copyOf(desc, desc.length + 1);
desc[desc.length - 1] = pos;
- Transform key = Transform.of(Transform.Kind.LOCAL_TYPES, desc);
+ Transform key = Transform.of(Transform.LOCAL_TYPES, desc);
LambdaForm form = getInCache(key);
if (form != null) {
return form;
}
< prev index next >