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() {
|