src/share/classes/java/lang/invoke/MethodTypeForm.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodTypeForm.java

Print this page
rev 10274 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10275 : imported patch invokers


  34  * Shared information for a group of method types, which differ
  35  * only by reference types, and therefore share a common erasure
  36  * and wrapping.
  37  * <p>
  38  * For an empirical discussion of the structure of method types,
  39  * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
  40  * the thread "Avoiding Boxing" on jvm-languages</a>.
  41  * There are approximately 2000 distinct erased method types in the JDK.
  42  * There are a little over 10 times that number of unerased types.
  43  * No more than half of these are likely to be loaded at once.
  44  * @author John Rose
  45  */
  46 final class MethodTypeForm {
  47     final int[] argToSlotTable, slotToArgTable;
  48     final long argCounts;               // packed slot & value counts
  49     final long primCounts;              // packed prim & double counts
  50     final MethodType erasedType;        // the canonical erasure
  51     final MethodType basicType;         // the canonical erasure, with primitives simplified
  52 
  53     // Cached adapter information:
  54     @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction






  55 
  56     // Cached lambda form information, for basic types only:
  57     final @Stable LambdaForm[] lambdaForms;
  58     // Indexes into lambdaForms:
  59     static final int
  60             LF_INVVIRTUAL     =  0,  // DMH invokeVirtual
  61             LF_INVSTATIC      =  1,
  62             LF_INVSPECIAL     =  2,
  63             LF_NEWINVSPECIAL  =  3,
  64             LF_INVINTERFACE   =  4,
  65             LF_INVSTATIC_INIT =  5,  // DMH invokeStatic with <clinit> barrier
  66             LF_INTERPRET      =  6,  // LF interpreter
  67             LF_COUNTER        =  7,  // CMH wrapper
  68             LF_REINVOKE       =  8,  // other wrapper
  69             LF_EX_LINKER      =  9,  // invokeExact_MT (for invokehandle)
  70             LF_EX_INVOKER     = 10,  // MHs.invokeExact
  71             LF_GEN_LINKER     = 11,  // generic invoke_MT (for invokehandle)
  72             LF_GEN_INVOKER    = 12,  // generic MHs.invoke
  73             LF_CS_LINKER      = 13,  // linkToCallSite_CS
  74             LF_MH_LINKER      = 14,  // linkToCallSite_MH


  81     public MethodType erasedType() {
  82         return erasedType;
  83     }
  84 
  85     /** Return the basic type derived from the erased type of this MT-form.
  86      *  A basic type is erased (all references Object) and also has all primitive
  87      *  types (except int, long, float, double, void) normalized to int.
  88      *  Such basic types correspond to low-level JVM calling sequences.
  89      */
  90     public MethodType basicType() {
  91         return basicType;
  92     }
  93 
  94     private boolean assertIsBasicType() {
  95         // primitives must be flattened also
  96         assert(erasedType == basicType)
  97                 : "erasedType: " + erasedType + " != basicType: " + basicType;
  98         return true;
  99     }
 100 












 101     public LambdaForm cachedLambdaForm(int which) {
 102         assert(assertIsBasicType());
 103         return lambdaForms[which];
 104     }
 105 
 106     synchronized public LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
 107         // Simulate a CAS, to avoid racy duplication of results.
 108         LambdaForm prev = lambdaForms[which];
 109         if (prev != null) return prev;
 110         return lambdaForms[which] = form;
 111     }
 112 
 113     /**
 114      * Build an MTF for a given type, which must have all references erased to Object.
 115      * This MTF will stand for that type and all un-erased variations.
 116      * Eagerly compute some basic properties of the type, common to all variations.
 117      */
 118     protected MethodTypeForm(MethodType erasedType) {
 119         this.erasedType = erasedType;
 120 


 152             if (w.isDoubleWord())  ++lrc;
 153             if (w.isSubwordOrInt() && rt != int.class)
 154                 bt = int.class;
 155             // adjust #slots, #args
 156             if (rt == void.class)
 157                 rtypeCount = rslotCount = 0;
 158             else
 159                 rslotCount += lrc;
 160         }
 161         if (epts == bpts && bt == rt) {
 162             this.basicType = erasedType;
 163         } else {
 164             this.basicType = MethodType.makeImpl(bt, bpts, true);
 165             // fill in rest of data from the basic type:
 166             MethodTypeForm that = this.basicType.form();
 167             assert(this != that);
 168             this.primCounts = that.primCounts;
 169             this.argCounts = that.argCounts;
 170             this.argToSlotTable = that.argToSlotTable;
 171             this.slotToArgTable = that.slotToArgTable;

 172             this.lambdaForms = null;
 173             return;
 174         }
 175         if (lac != 0) {
 176             int slot = ptypeCount + lac;
 177             slotToArgTab = new int[slot+1];
 178             argToSlotTab = new int[1+ptypeCount];
 179             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
 180             for (int i = 0; i < epts.length; i++) {
 181                 Class<?> pt = epts[i];
 182                 Wrapper w = Wrapper.forBasicType(pt);
 183                 if (w.isDoubleWord())  --slot;
 184                 --slot;
 185                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
 186                 argToSlotTab[1+i]  = slot;
 187             }
 188             assert(slot == 0);  // filled the table
 189         } else if (pac != 0) {
 190             // have primitives but no long primitives; share slot counts with generic
 191             assert(ptypeCount == pslotCount);


 197             int slot = ptypeCount; // first arg is deepest in stack
 198             slotToArgTab = new int[slot+1];
 199             argToSlotTab = new int[1+ptypeCount];
 200             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
 201             for (int i = 0; i < ptypeCount; i++) {
 202                 --slot;
 203                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
 204                 argToSlotTab[1+i]  = slot;
 205             }
 206         }
 207         this.primCounts = pack(lrc, prc, lac, pac);
 208         this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
 209         this.argToSlotTable = argToSlotTab;
 210         this.slotToArgTable = slotToArgTab;
 211 
 212         if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 213 
 214         // Initialize caches, but only for basic types
 215         assert(basicType == erasedType);
 216         this.lambdaForms = new LambdaForm[LF_LIMIT];

 217     }
 218 
 219     private static long pack(int a, int b, int c, int d) {
 220         assert(((a|b|c|d) & ~0xFFFF) == 0);
 221         long hw = ((a << 16) | b), lw = ((c << 16) | d);
 222         return (hw << 32) | lw;
 223     }
 224     private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
 225         assert(word <= 3);
 226         return (char)(packed >> ((3-word) * 16));
 227     }
 228 
 229     public int parameterCount() {                      // # outgoing values
 230         return unpack(argCounts, 3);
 231     }
 232     public int parameterSlotCount() {                  // # outgoing interpreter slots
 233         return unpack(argCounts, 2);
 234     }
 235     public int returnCount() {                         // = 0 (V), or 1
 236         return unpack(argCounts, 1);




  34  * Shared information for a group of method types, which differ
  35  * only by reference types, and therefore share a common erasure
  36  * and wrapping.
  37  * <p>
  38  * For an empirical discussion of the structure of method types,
  39  * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
  40  * the thread "Avoiding Boxing" on jvm-languages</a>.
  41  * There are approximately 2000 distinct erased method types in the JDK.
  42  * There are a little over 10 times that number of unerased types.
  43  * No more than half of these are likely to be loaded at once.
  44  * @author John Rose
  45  */
  46 final class MethodTypeForm {
  47     final int[] argToSlotTable, slotToArgTable;
  48     final long argCounts;               // packed slot & value counts
  49     final long primCounts;              // packed prim & double counts
  50     final MethodType erasedType;        // the canonical erasure
  51     final MethodType basicType;         // the canonical erasure, with primitives simplified
  52 
  53     // Cached adapter information:
  54     @Stable final MethodHandle[] methodHandles;
  55     // Indexes into methodHandles:
  56     static final int
  57             MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
  58             MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
  59             MH_UNINIT_CS      =  2,  // uninitialized call site
  60             MH_LIMIT          =  3;
  61 
  62     // Cached lambda form information, for basic types only:
  63     final @Stable LambdaForm[] lambdaForms;
  64     // Indexes into lambdaForms:
  65     static final int
  66             LF_INVVIRTUAL     =  0,  // DMH invokeVirtual
  67             LF_INVSTATIC      =  1,
  68             LF_INVSPECIAL     =  2,
  69             LF_NEWINVSPECIAL  =  3,
  70             LF_INVINTERFACE   =  4,
  71             LF_INVSTATIC_INIT =  5,  // DMH invokeStatic with <clinit> barrier
  72             LF_INTERPRET      =  6,  // LF interpreter
  73             LF_COUNTER        =  7,  // CMH wrapper
  74             LF_REINVOKE       =  8,  // other wrapper
  75             LF_EX_LINKER      =  9,  // invokeExact_MT (for invokehandle)
  76             LF_EX_INVOKER     = 10,  // MHs.invokeExact
  77             LF_GEN_LINKER     = 11,  // generic invoke_MT (for invokehandle)
  78             LF_GEN_INVOKER    = 12,  // generic MHs.invoke
  79             LF_CS_LINKER      = 13,  // linkToCallSite_CS
  80             LF_MH_LINKER      = 14,  // linkToCallSite_MH


  87     public MethodType erasedType() {
  88         return erasedType;
  89     }
  90 
  91     /** Return the basic type derived from the erased type of this MT-form.
  92      *  A basic type is erased (all references Object) and also has all primitive
  93      *  types (except int, long, float, double, void) normalized to int.
  94      *  Such basic types correspond to low-level JVM calling sequences.
  95      */
  96     public MethodType basicType() {
  97         return basicType;
  98     }
  99 
 100     private boolean assertIsBasicType() {
 101         // primitives must be flattened also
 102         assert(erasedType == basicType)
 103                 : "erasedType: " + erasedType + " != basicType: " + basicType;
 104         return true;
 105     }
 106 
 107     public MethodHandle cachedMethodHandle(int which) {
 108         assert(assertIsBasicType());
 109         return methodHandles[which];
 110     }
 111 
 112     synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
 113         // Simulate a CAS, to avoid racy duplication of results.
 114         MethodHandle prev = methodHandles[which];
 115         if (prev != null)  return prev;
 116         return methodHandles[which] = mh;
 117     }
 118 
 119     public LambdaForm cachedLambdaForm(int which) {
 120         assert(assertIsBasicType());
 121         return lambdaForms[which];
 122     }
 123 
 124     synchronized public LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
 125         // Simulate a CAS, to avoid racy duplication of results.
 126         LambdaForm prev = lambdaForms[which];
 127         if (prev != null) return prev;
 128         return lambdaForms[which] = form;
 129     }
 130 
 131     /**
 132      * Build an MTF for a given type, which must have all references erased to Object.
 133      * This MTF will stand for that type and all un-erased variations.
 134      * Eagerly compute some basic properties of the type, common to all variations.
 135      */
 136     protected MethodTypeForm(MethodType erasedType) {
 137         this.erasedType = erasedType;
 138 


 170             if (w.isDoubleWord())  ++lrc;
 171             if (w.isSubwordOrInt() && rt != int.class)
 172                 bt = int.class;
 173             // adjust #slots, #args
 174             if (rt == void.class)
 175                 rtypeCount = rslotCount = 0;
 176             else
 177                 rslotCount += lrc;
 178         }
 179         if (epts == bpts && bt == rt) {
 180             this.basicType = erasedType;
 181         } else {
 182             this.basicType = MethodType.makeImpl(bt, bpts, true);
 183             // fill in rest of data from the basic type:
 184             MethodTypeForm that = this.basicType.form();
 185             assert(this != that);
 186             this.primCounts = that.primCounts;
 187             this.argCounts = that.argCounts;
 188             this.argToSlotTable = that.argToSlotTable;
 189             this.slotToArgTable = that.slotToArgTable;
 190             this.methodHandles = null;
 191             this.lambdaForms = null;
 192             return;
 193         }
 194         if (lac != 0) {
 195             int slot = ptypeCount + lac;
 196             slotToArgTab = new int[slot+1];
 197             argToSlotTab = new int[1+ptypeCount];
 198             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
 199             for (int i = 0; i < epts.length; i++) {
 200                 Class<?> pt = epts[i];
 201                 Wrapper w = Wrapper.forBasicType(pt);
 202                 if (w.isDoubleWord())  --slot;
 203                 --slot;
 204                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
 205                 argToSlotTab[1+i]  = slot;
 206             }
 207             assert(slot == 0);  // filled the table
 208         } else if (pac != 0) {
 209             // have primitives but no long primitives; share slot counts with generic
 210             assert(ptypeCount == pslotCount);


 216             int slot = ptypeCount; // first arg is deepest in stack
 217             slotToArgTab = new int[slot+1];
 218             argToSlotTab = new int[1+ptypeCount];
 219             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
 220             for (int i = 0; i < ptypeCount; i++) {
 221                 --slot;
 222                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
 223                 argToSlotTab[1+i]  = slot;
 224             }
 225         }
 226         this.primCounts = pack(lrc, prc, lac, pac);
 227         this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
 228         this.argToSlotTable = argToSlotTab;
 229         this.slotToArgTable = slotToArgTab;
 230 
 231         if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 232 
 233         // Initialize caches, but only for basic types
 234         assert(basicType == erasedType);
 235         this.lambdaForms = new LambdaForm[LF_LIMIT];
 236         this.methodHandles = new MethodHandle[MH_LIMIT];
 237     }
 238 
 239     private static long pack(int a, int b, int c, int d) {
 240         assert(((a|b|c|d) & ~0xFFFF) == 0);
 241         long hw = ((a << 16) | b), lw = ((c << 16) | d);
 242         return (hw << 32) | lw;
 243     }
 244     private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
 245         assert(word <= 3);
 246         return (char)(packed >> ((3-word) * 16));
 247     }
 248 
 249     public int parameterCount() {                      // # outgoing values
 250         return unpack(argCounts, 3);
 251     }
 252     public int parameterSlotCount() {                  // # outgoing interpreter slots
 253         return unpack(argCounts, 2);
 254     }
 255     public int returnCount() {                         // = 0 (V), or 1
 256         return unpack(argCounts, 1);


src/share/classes/java/lang/invoke/MethodTypeForm.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File