jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
changeset 40256 c5e03eaf7ba2
parent 39342 f66a89ed6fca
child 40810 b88d5910ea1e
equal deleted inserted replaced
40255:0222e4232e7c 40256:c5e03eaf7ba2
    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,
   129             }
   134             }
   130             assert(packedBytes(bytes) == 0);
   135             assert(packedBytes(bytes) == 0);
   131             return bytes;
   136             return bytes;
   132         }
   137         }
   133 
   138 
   134         private byte byteAt(int i) {
       
   135             long pb = packedBytes;
       
   136             if (pb == 0) {
       
   137                 if (i >= fullBytes.length)  return 0;
       
   138                 return fullBytes[i];
       
   139             }
       
   140             assert(fullBytes == null);
       
   141             if (i > PACKED_BYTE_MAX_LENGTH)  return 0;
       
   142             int pos = (i * PACKED_BYTE_SIZE);
       
   143             return (byte)((pb >>> pos) & PACKED_BYTE_MASK);
       
   144         }
       
   145 
       
   146         Kind kind() { return Kind.values()[byteAt(0)]; }
       
   147 
       
   148         private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
   139         private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
   149             super(result);
   140             super(result);
   150             this.packedBytes = packedBytes;
   141             this.packedBytes = packedBytes;
   151             this.fullBytes = fullBytes;
   142             this.fullBytes = fullBytes;
   152         }
   143         }
   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;
   447 
   433 
   448     /// Editing methods for lambda forms.
   434     /// Editing methods for lambda forms.
   449     // Each editing method can (potentially) cache the edited LF so that it can be reused later.
   435     // Each editing method can (potentially) cache the edited LF so that it can be reused later.
   450 
   436 
   451     LambdaForm bindArgumentForm(int pos) {
   437     LambdaForm bindArgumentForm(int pos) {
   452         Transform key = Transform.of(Transform.Kind.BIND_ARG, pos);
   438         Transform key = Transform.of(Transform.BIND_ARG, pos);
   453         LambdaForm form = getInCache(key);
   439         LambdaForm form = getInCache(key);
   454         if (form != null) {
   440         if (form != null) {
   455             assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
   441             assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
   456             return form;
   442             return form;
   457         }
   443         }
   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;
   499         form = buf.endEdit();
   485         form = buf.endEdit();
   500         return putInCache(key, form);
   486         return putInCache(key, form);
   501     }
   487     }
   502 
   488 
   503     LambdaForm dupArgumentForm(int srcPos, int dstPos) {
   489     LambdaForm dupArgumentForm(int srcPos, int dstPos) {
   504         Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos);
   490         Transform key = Transform.of(Transform.DUP_ARG, srcPos, dstPos);
   505         LambdaForm form = getInCache(key);
   491         LambdaForm form = getInCache(key);
   506         if (form != null) {
   492         if (form != null) {
   507             assert(form.arity == lambdaForm.arity-1);
   493             assert(form.arity == lambdaForm.arity-1);
   508             return form;
   494             return form;
   509         }
   495         }
   528         if (bt.basicTypeClass() != elementType) {
   514         if (bt.basicTypeClass() != elementType) {
   529             if (elementType.isPrimitive()) {
   515             if (elementType.isPrimitive()) {
   530                 elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
   516                 elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
   531             }
   517             }
   532         }
   518         }
   533         Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
   519         Transform key = Transform.of(Transform.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
   534         LambdaForm form = getInCache(key);
   520         LambdaForm form = getInCache(key);
   535         if (form != null) {
   521         if (form != null) {
   536             assert(form.arity == lambdaForm.arity - arrayLength + 1);
   522             assert(form.arity == lambdaForm.arity - arrayLength + 1);
   537             return form;
   523             return form;
   538         }
   524         }
   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;
   708 
   694 
   709         return buf.endEdit();
   695         return buf.endEdit();
   710     }
   696     }
   711 
   697 
   712     LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
   698     LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
   713         Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN);
   699         byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN);
   714         Transform key = Transform.of(kind, newType.ordinal());
   700         Transform key = Transform.of(kind, newType.ordinal());
   715         LambdaForm form = getInCache(key);
   701         LambdaForm form = getInCache(key);
   716         if (form != null) {
   702         if (form != null) {
   717             assert(form.arity == lambdaForm.arity);
   703             assert(form.arity == lambdaForm.arity);
   718             assert(form.returnType() == newType);
   704             assert(form.returnType() == newType);
   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     }
   784             if (inArg != i)  nullPerm = false;
   770             if (inArg != i)  nullPerm = false;
   785             inTypes = Math.max(inTypes, inArg+1);
   771             inTypes = Math.max(inTypes, inArg+1);
   786         }
   772         }
   787         assert(skip + reorder.length == lambdaForm.arity);
   773         assert(skip + reorder.length == lambdaForm.arity);
   788         if (nullPerm)  return lambdaForm;  // do not bother to cache
   774         if (nullPerm)  return lambdaForm;  // do not bother to cache
   789         Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder);
   775         Transform key = Transform.of(Transform.PERMUTE_ARGS, reorder);
   790         LambdaForm form = getInCache(key);
   776         LambdaForm form = getInCache(key);
   791         if (form != null) {
   777         if (form != null) {
   792             assert(form.arity == skip+inTypes) : form;
   778             assert(form.arity == skip+inTypes) : form;
   793             return form;
   779             return form;
   794         }
   780         }
   853     LambdaForm noteLoopLocalTypesForm(int pos, BasicType[] localTypes) {
   839     LambdaForm noteLoopLocalTypesForm(int pos, BasicType[] localTypes) {
   854         assert(lambdaForm.isLoop(pos));
   840         assert(lambdaForm.isLoop(pos));
   855         int[] desc = BasicType.basicTypeOrds(localTypes);
   841         int[] desc = BasicType.basicTypeOrds(localTypes);
   856         desc = Arrays.copyOf(desc, desc.length + 1);
   842         desc = Arrays.copyOf(desc, desc.length + 1);
   857         desc[desc.length - 1] = pos;
   843         desc[desc.length - 1] = pos;
   858         Transform key = Transform.of(Transform.Kind.LOCAL_TYPES, desc);
   844         Transform key = Transform.of(Transform.LOCAL_TYPES, desc);
   859         LambdaForm form = getInCache(key);
   845         LambdaForm form = getInCache(key);
   860         if (form != null) {
   846         if (form != null) {
   861             return form;
   847             return form;
   862         }
   848         }
   863 
   849