< prev index next >

src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java

Print this page

  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import sun.invoke.util.Wrapper;
  29 
  30 import java.lang.ref.SoftReference;
  31 import java.util.Arrays;
  32 import java.util.Comparator;
  33 import java.util.TreeMap;
  34 import java.util.concurrent.ConcurrentHashMap;
  35 
  36 import static java.lang.invoke.LambdaForm.*;
  37 import static java.lang.invoke.LambdaForm.BasicType.*;
  38 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
  39 import static java.lang.invoke.MethodHandleImpl.NF_loop;
  40 import static java.lang.invoke.MethodHandleImpl.makeIntrinsic;

  41 
  42 /** Transforms on LFs.
  43  *  A lambda-form editor can derive new LFs from its base LF.
  44  *  The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes.
  45  *  To support this caching, a LF has an optional pointer to its editor.
  46  */
  47 class LambdaFormEditor {
  48     final LambdaForm lambdaForm;
  49 
  50     private LambdaFormEditor(LambdaForm lambdaForm) {
  51         this.lambdaForm = lambdaForm;
  52     }
  53 
  54     // Factory method.
  55     static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) {
  56         // TO DO:  Consider placing intern logic here, to cut down on duplication.
  57         // lambdaForm = findPreexistingEquivalent(lambdaForm)
  58 
  59         // Always use uncustomized version for editing.
  60         // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version.

  72             FILTER_RETURN = 6,
  73             COLLECT_ARGS = 7,
  74             COLLECT_ARGS_TO_VOID = 8,
  75             REPEAT_FILTER_ARGS = 9,
  76             FOLD_ARGS = 10,
  77             FOLD_ARGS_TO_VOID = 11,
  78             PERMUTE_ARGS = 12,
  79             LOCAL_TYPES = 13,
  80             FILTER_SELECT_ARGS = 14,
  81             FOLD_SELECT_ARGS = 15;
  82 
  83     /**
  84      * A description of a cached transform, possibly associated with the result of the transform.
  85      * The logical content is a sequence of byte values, starting with a kind value.
  86      * The sequence is unterminated, ending with an indefinite number of zero bytes.
  87      * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
  88      *
  89      * Tightly coupled with the TransformKey class, which is used to lookup existing
  90      * Transforms.
  91      */
  92     private static final class Transform extends SoftReference<LambdaForm> {

  93         final long packedBytes;
  94         final byte[] fullBytes;
  95 
  96         private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
  97             super(result);




  98             this.packedBytes = packedBytes;
  99             this.fullBytes = fullBytes;
 100         }
 101 
 102         @Override
 103         public boolean equals(Object obj) {
 104             if (obj instanceof TransformKey key) {
 105                 return equals(key);
 106             }
 107             return obj instanceof Transform transform && equals(transform);
 108         }
 109 
 110         private boolean equals(TransformKey that) {
 111             return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
 112         }
 113 
 114         private boolean equals(Transform that) {
 115             return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
 116         }
 117 
 118         @Override
 119         public int hashCode() {
 120             if (packedBytes != 0) {
 121                 assert(fullBytes == null);
 122                 return Long.hashCode(packedBytes);
 123             }
 124             return Arrays.hashCode(fullBytes);
 125         }
 126 
 127         @Override
 128         public String toString() {
 129             StringBuilder buf = new StringBuilder();
 130             buf.append(new TransformKey(packedBytes, fullBytes).toString());
 131             LambdaForm result = get();
 132             if (result != null) {
 133                 buf.append(" result=");
 134                 buf.append(result);
 135             }
 136             return buf.toString();
 137         }









 138     }
 139 
 140     /**
 141      * Used as a lookup key to find existing Transforms
 142      */
 143     private static final class TransformKey {
 144         final long packedBytes;
 145         final byte[] fullBytes;
 146 
 147         private TransformKey(long packedBytes) {
 148             this.packedBytes = packedBytes;
 149             this.fullBytes = null;
 150         }
 151 
 152         private TransformKey(byte[] fullBytes) {
 153             assert(packedBytes(fullBytes) == 0);
 154             this.fullBytes = fullBytes;
 155             this.packedBytes = 0;
 156         }
 157 

  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import sun.invoke.util.Wrapper;
  29 
  30 import java.lang.ref.SoftReference;
  31 import java.util.Arrays;
  32 import java.util.Comparator;
  33 import java.util.TreeMap;
  34 import java.util.concurrent.ConcurrentHashMap;
  35 
  36 import static java.lang.invoke.LambdaForm.*;
  37 import static java.lang.invoke.LambdaForm.BasicType.*;
  38 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
  39 import static java.lang.invoke.MethodHandleImpl.NF_loop;
  40 import static java.lang.invoke.MethodHandleImpl.makeIntrinsic;
  41 import static java.lang.invoke.MethodHandleStatics.NO_SOFT_CACHE;
  42 
  43 /** Transforms on LFs.
  44  *  A lambda-form editor can derive new LFs from its base LF.
  45  *  The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes.
  46  *  To support this caching, a LF has an optional pointer to its editor.
  47  */
  48 class LambdaFormEditor {
  49     final LambdaForm lambdaForm;
  50 
  51     private LambdaFormEditor(LambdaForm lambdaForm) {
  52         this.lambdaForm = lambdaForm;
  53     }
  54 
  55     // Factory method.
  56     static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) {
  57         // TO DO:  Consider placing intern logic here, to cut down on duplication.
  58         // lambdaForm = findPreexistingEquivalent(lambdaForm)
  59 
  60         // Always use uncustomized version for editing.
  61         // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version.

  73             FILTER_RETURN = 6,
  74             COLLECT_ARGS = 7,
  75             COLLECT_ARGS_TO_VOID = 8,
  76             REPEAT_FILTER_ARGS = 9,
  77             FOLD_ARGS = 10,
  78             FOLD_ARGS_TO_VOID = 11,
  79             PERMUTE_ARGS = 12,
  80             LOCAL_TYPES = 13,
  81             FILTER_SELECT_ARGS = 14,
  82             FOLD_SELECT_ARGS = 15;
  83 
  84     /**
  85      * A description of a cached transform, possibly associated with the result of the transform.
  86      * The logical content is a sequence of byte values, starting with a kind value.
  87      * The sequence is unterminated, ending with an indefinite number of zero bytes.
  88      * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
  89      *
  90      * Tightly coupled with the TransformKey class, which is used to lookup existing
  91      * Transforms.
  92      */
  93     private static final class Transform {
  94         final Object cache;
  95         final long packedBytes;
  96         final byte[] fullBytes;
  97 
  98         private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
  99             if (NO_SOFT_CACHE) {
 100                 cache = result;
 101             } else {
 102                 cache = new SoftReference<LambdaForm>(result);
 103             }
 104             this.packedBytes = packedBytes;
 105             this.fullBytes = fullBytes;
 106         }
 107 
 108         @Override
 109         public boolean equals(Object obj) {
 110             if (obj instanceof TransformKey key) {
 111                 return equals(key);
 112             }
 113             return obj instanceof Transform transform && equals(transform);
 114         }
 115 
 116         private boolean equals(TransformKey that) {
 117             return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
 118         }
 119 
 120         private boolean equals(Transform that) {
 121             return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
 122         }
 123 
 124         @Override
 125         public int hashCode() {
 126             if (packedBytes != 0) {
 127                 assert(fullBytes == null);
 128                 return Long.hashCode(packedBytes);
 129             }
 130             return Arrays.hashCode(fullBytes);
 131         }
 132 
 133         @Override
 134         public String toString() {
 135             StringBuilder buf = new StringBuilder();
 136             buf.append(new TransformKey(packedBytes, fullBytes).toString());
 137             LambdaForm result = get();
 138             if (result != null) {
 139                 buf.append(" result=");
 140                 buf.append(result);
 141             }
 142             return buf.toString();
 143         }
 144 
 145         @SuppressWarnings({"rawtypes", "unchecked"})
 146         public LambdaForm get() {
 147             if (cache instanceof LambdaForm) {
 148                 return (LambdaForm)cache;
 149             } else {
 150                 return ((SoftReference<LambdaForm>)cache).get();
 151             }
 152         }
 153     }
 154 
 155     /**
 156      * Used as a lookup key to find existing Transforms
 157      */
 158     private static final class TransformKey {
 159         final long packedBytes;
 160         final byte[] fullBytes;
 161 
 162         private TransformKey(long packedBytes) {
 163             this.packedBytes = packedBytes;
 164             this.fullBytes = null;
 165         }
 166 
 167         private TransformKey(byte[] fullBytes) {
 168             assert(packedBytes(fullBytes) == 0);
 169             this.fullBytes = fullBytes;
 170             this.packedBytes = 0;
 171         }
 172 
< prev index next >