< prev index next >

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

Print this page

 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 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 
 32 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;

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

 92             LF_VH_GEN_LINKER           = 24,  // VarHandle generic linker
 93             LF_COLLECTOR               = 25,  // collector handle
 94             LF_LIMIT                   = 26;
 95 
 96     /** Return the type corresponding uniquely (1-1) to this MT-form.
 97      *  It might have any primitive returns or arguments, but will have no references except Object.
 98      */
 99     public MethodType erasedType() {
100         return erasedType;
101     }
102 
103     /** Return the basic type derived from the erased type of this MT-form.
104      *  A basic type is erased (all references Object) and also has all primitive
105      *  types (except int, long, float, double, void) normalized to int.
106      *  Such basic types correspond to low-level JVM calling sequences.
107      */
108     public MethodType basicType() {
109         return basicType;
110     }
111 

112     public MethodHandle cachedMethodHandle(int which) {
113         SoftReference<MethodHandle> entry = methodHandles[which];
114         return (entry != null) ? entry.get() : null;






115     }
116 
117     public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
118         // Simulate a CAS, to avoid racy duplication of results.
119         SoftReference<MethodHandle> entry = methodHandles[which];
120         if (entry != null) {
121             MethodHandle prev = entry.get();
122             if (prev != null) {
123                 return prev;
124             }


125         }
126         methodHandles[which] = new SoftReference<>(mh);
127         return mh;
128     }
129 

130     public LambdaForm cachedLambdaForm(int which) {
131         SoftReference<LambdaForm> entry = lambdaForms[which];
132         return (entry != null) ? entry.get() : null;






133     }
134 
135     public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
136         // Simulate a CAS, to avoid racy duplication of results.
137         SoftReference<LambdaForm> entry = lambdaForms[which];
138         if (entry != null) {
139             LambdaForm prev = entry.get();
140             if (prev != null) {
141                 return prev;
142             }


143         }
144         lambdaForms[which] = new SoftReference<>(form);
145         return form;
146     }
147 
148     /**
149      * Build an MTF for a given type, which must have all references erased to Object.
150      * This MTF will stand for that type and all un-erased variations.
151      * Eagerly compute some basic properties of the type, common to all variations.
152      */
153     @SuppressWarnings({"rawtypes", "unchecked"})
154     protected MethodTypeForm(MethodType erasedType) {
155         this.erasedType = erasedType;
156 
157         Class<?>[] ptypes = erasedType.ptypes();
158         int pslotCount = ptypes.length;
159 
160         // Walk the argument types, looking for primitives.
161         short primitiveCount = 0, longArgCount = 0;
162         Class<?>[] erasedPtypes = ptypes;
163         Class<?>[] basicPtypes = erasedPtypes;
164         for (int i = 0; i < erasedPtypes.length; i++) {

174                 }
175             }
176         }
177         pslotCount += longArgCount;                  // #slots = #args + #longs
178         Class<?> returnType = erasedType.returnType();
179         Class<?> basicReturnType = returnType;
180         if (returnType != Object.class) {
181             ++primitiveCount; // even void.class counts as a prim here
182             Wrapper w = Wrapper.forPrimitiveType(returnType);
183             if (w.isSubwordOrInt() && returnType != int.class)
184                 basicReturnType = int.class;
185         }
186         if (erasedPtypes == basicPtypes && basicReturnType == returnType) {
187             // Basic type
188             this.basicType = erasedType;
189 
190             if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
191 
192             this.primitiveCount = primitiveCount;
193             this.parameterSlotCount = (short)pslotCount;
194             this.lambdaForms   = new SoftReference[LF_LIMIT];
195             this.methodHandles = new SoftReference[MH_LIMIT];
196         } else {
197             this.basicType = MethodType.methodType(basicReturnType, basicPtypes, true);
198             // fill in rest of data from the basic type:
199             MethodTypeForm that = this.basicType.form();
200             assert(this != that);
201 
202             this.parameterSlotCount = that.parameterSlotCount;
203             this.primitiveCount = that.primitiveCount;
204             this.methodHandles = null;
205             this.lambdaForms = null;
206         }
207     }
208 
209     public int parameterCount() {
210         return erasedType.parameterCount();
211     }
212     public int parameterSlotCount() {
213         return parameterSlotCount;
214     }
215     public boolean hasPrimitives() {

 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 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 
 32 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
 33 import static java.lang.invoke.MethodHandleStatics.NO_SOFT_CACHE;
 34 
 35 /**
 36  * Shared information for a group of method types, which differ
 37  * only by reference types, and therefore share a common erasure
 38  * and wrapping.
 39  * <p>
 40  * For an empirical discussion of the structure of method types,
 41  * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
 42  * the thread "Avoiding Boxing" on jvm-languages</a>.
 43  * There are approximately 2000 distinct erased method types in the JDK.
 44  * There are a little over 10 times that number of unerased types.
 45  * No more than half of these are likely to be loaded at once.
 46  * @author John Rose
 47  */
 48 final class MethodTypeForm {
 49     final short parameterSlotCount;
 50     final short primitiveCount;
 51     final MethodType erasedType;        // the canonical erasure
 52     final MethodType basicType;         // the canonical erasure, with primitives simplified
 53 
 54     // Cached adapter information:
 55     private final Object[] methodHandles;
 56 
 57     // Indexes into methodHandles:
 58     static final int
 59             MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
 60             MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
 61             MH_UNINIT_CS      =  2,  // uninitialized call site
 62             MH_LIMIT          =  3;
 63 
 64     // Cached lambda form information, for basic types only:
 65     private final Object[] lambdaForms;
 66 
 67     // Indexes into lambdaForms:
 68     static final int
 69             LF_INVVIRTUAL              =  0,  // DMH invokeVirtual
 70             LF_INVSTATIC               =  1,
 71             LF_INVSPECIAL              =  2,
 72             LF_NEWINVSPECIAL           =  3,
 73             LF_INVINTERFACE            =  4,
 74             LF_INVSTATIC_INIT          =  5,  // DMH invokeStatic with <clinit> barrier
 75             LF_INTERPRET               =  6,  // LF interpreter
 76             LF_REBIND                  =  7,  // BoundMethodHandle
 77             LF_DELEGATE                =  8,  // DelegatingMethodHandle
 78             LF_DELEGATE_BLOCK_INLINING =  9,  // Counting DelegatingMethodHandle w/ @DontInline
 79             LF_EX_LINKER               = 10,  // invokeExact_MT (for invokehandle)
 80             LF_EX_INVOKER              = 11,  // MHs.invokeExact
 81             LF_GEN_LINKER              = 12,  // generic invoke_MT (for invokehandle)
 82             LF_GEN_INVOKER             = 13,  // generic MHs.invoke
 83             LF_CS_LINKER               = 14,  // linkToCallSite_CS
 84             LF_MH_LINKER               = 15,  // linkToCallSite_MH
 85             LF_GWC                     = 16,  // guardWithCatch (catchException)

 93             LF_VH_GEN_LINKER           = 24,  // VarHandle generic linker
 94             LF_COLLECTOR               = 25,  // collector handle
 95             LF_LIMIT                   = 26;
 96 
 97     /** Return the type corresponding uniquely (1-1) to this MT-form.
 98      *  It might have any primitive returns or arguments, but will have no references except Object.
 99      */
100     public MethodType erasedType() {
101         return erasedType;
102     }
103 
104     /** Return the basic type derived from the erased type of this MT-form.
105      *  A basic type is erased (all references Object) and also has all primitive
106      *  types (except int, long, float, double, void) normalized to int.
107      *  Such basic types correspond to low-level JVM calling sequences.
108      */
109     public MethodType basicType() {
110         return basicType;
111     }
112 
113     @SuppressWarnings({"rawtypes", "unchecked"})
114     public MethodHandle cachedMethodHandle(int which) {
115         Object entry = methodHandles[which];
116         if (entry == null) {
117             return null;
118         } else if (entry instanceof MethodHandle) {
119             return (MethodHandle) entry;
120         } else {
121             return ((SoftReference<MethodHandle>)entry).get();
122         }
123     }
124 
125     public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
126         // Simulate a CAS, to avoid racy duplication of results.
127         MethodHandle prev = cachedMethodHandle(which);
128         if (prev != null) {
129             return prev;
130         }
131         if (NO_SOFT_CACHE) {
132             methodHandles[which] = mh;
133         } else {
134             methodHandles[which] = new SoftReference<>(mh);
135         }

136         return mh;
137     }
138 
139     @SuppressWarnings({"rawtypes", "unchecked"})
140     public LambdaForm cachedLambdaForm(int which) {
141         Object entry = lambdaForms[which];
142         if (entry == null) {
143             return null;
144         } else if (entry instanceof LambdaForm) {
145             return (LambdaForm) entry;
146         } else {
147             return ((SoftReference<LambdaForm>)entry).get();
148         }
149     }
150 
151     public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
152         // Simulate a CAS, to avoid racy duplication of results.
153         LambdaForm prev = cachedLambdaForm(which);
154         if (prev != null) {
155             return prev;
156         }
157         if (NO_SOFT_CACHE) {
158             lambdaForms[which] = form;
159         } else {
160             lambdaForms[which] = new SoftReference<>(form);
161         }

162         return form;
163     }
164 
165     /**
166      * Build an MTF for a given type, which must have all references erased to Object.
167      * This MTF will stand for that type and all un-erased variations.
168      * Eagerly compute some basic properties of the type, common to all variations.
169      */
170     @SuppressWarnings({"rawtypes", "unchecked"})
171     protected MethodTypeForm(MethodType erasedType) {
172         this.erasedType = erasedType;
173 
174         Class<?>[] ptypes = erasedType.ptypes();
175         int pslotCount = ptypes.length;
176 
177         // Walk the argument types, looking for primitives.
178         short primitiveCount = 0, longArgCount = 0;
179         Class<?>[] erasedPtypes = ptypes;
180         Class<?>[] basicPtypes = erasedPtypes;
181         for (int i = 0; i < erasedPtypes.length; i++) {

191                 }
192             }
193         }
194         pslotCount += longArgCount;                  // #slots = #args + #longs
195         Class<?> returnType = erasedType.returnType();
196         Class<?> basicReturnType = returnType;
197         if (returnType != Object.class) {
198             ++primitiveCount; // even void.class counts as a prim here
199             Wrapper w = Wrapper.forPrimitiveType(returnType);
200             if (w.isSubwordOrInt() && returnType != int.class)
201                 basicReturnType = int.class;
202         }
203         if (erasedPtypes == basicPtypes && basicReturnType == returnType) {
204             // Basic type
205             this.basicType = erasedType;
206 
207             if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
208 
209             this.primitiveCount = primitiveCount;
210             this.parameterSlotCount = (short)pslotCount;
211             this.lambdaForms   = new Object[LF_LIMIT];
212             this.methodHandles = new Object[MH_LIMIT];
213         } else {
214             this.basicType = MethodType.methodType(basicReturnType, basicPtypes, true);
215             // fill in rest of data from the basic type:
216             MethodTypeForm that = this.basicType.form();
217             assert(this != that);
218 
219             this.parameterSlotCount = that.parameterSlotCount;
220             this.primitiveCount = that.primitiveCount;
221             this.methodHandles = null;
222             this.lambdaForms = null;
223         }
224     }
225 
226     public int parameterCount() {
227         return erasedType.parameterCount();
228     }
229     public int parameterSlotCount() {
230         return parameterSlotCount;
231     }
232     public boolean hasPrimitives() {
< prev index next >