103 * t3:L = MethodHandle#invoke(t2, a1);
104 * t4:L = FilterMethodHandle#target(a0);
105 * t5:L = MethodHandle#invoke(t4, t3); t5 }
106 * == general invoker for unary filterArgument combination
107 * (a0:L, a1:L)=>{ ...(same as previous example)...
108 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
109 * == general invoker for unary/unary foldArgument combination
110 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
111 * == invoker for identity method handle which performs i2l
112 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
113 * t3:L = Class#cast(t2,a1); t3 }
114 * == invoker for identity method handle which performs cast
115 * }</pre></blockquote>
116 * <p>
117 * @author John Rose, JSR 292 EG
118 */
119 class LambdaForm {
120 final int arity;
121 final int result;
122 final boolean forceInline;
123 @Stable final Name[] names;
124 final String debugName;
125 MemberName vmentry; // low-level behavior, or null if not yet prepared
126 private boolean isCompiled;
127
128 Object transformCache; // managed by LambdaFormEditor
129
130 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
131
132 enum BasicType {
133 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
134 I_TYPE('I', int.class, Wrapper.INT),
135 J_TYPE('J', long.class, Wrapper.LONG),
136 F_TYPE('F', float.class, Wrapper.FLOAT),
137 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
138 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
139
140 static final BasicType[] ALL_TYPES = BasicType.values();
141 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
142
227 return "LIJFD".indexOf(c) >= 0;
228 }
229
230 static { assert(checkBasicType()); }
231 private static boolean checkBasicType() {
232 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
233 assert ARG_TYPES[i].ordinal() == i;
234 assert ARG_TYPES[i] == ALL_TYPES[i];
235 }
236 for (int i = 0; i < TYPE_LIMIT; i++) {
237 assert ALL_TYPES[i].ordinal() == i;
238 }
239 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
240 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
241 return true;
242 }
243 }
244
245 LambdaForm(String debugName,
246 int arity, Name[] names, int result) {
247 this(debugName, arity, names, result, true);
248 }
249 LambdaForm(String debugName,
250 int arity, Name[] names, int result, boolean forceInline) {
251 assert(namesOK(arity, names));
252 this.arity = arity;
253 this.result = fixResult(result, names);
254 this.names = names.clone();
255 this.debugName = fixDebugName(debugName);
256 this.forceInline = forceInline;
257 int maxOutArity = normalize();
258 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
259 // Cannot use LF interpreter on very high arity expressions.
260 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
261 compileToBytecode();
262 }
263 }
264 LambdaForm(String debugName,
265 int arity, Name[] names) {
266 this(debugName, arity, names, LAST_RESULT, true);
267 }
268 LambdaForm(String debugName,
269 int arity, Name[] names, boolean forceInline) {
270 this(debugName, arity, names, LAST_RESULT, forceInline);
271 }
272 LambdaForm(String debugName,
273 Name[] formals, Name[] temps, Name result) {
274 this(debugName,
275 formals.length, buildNames(formals, temps, result), LAST_RESULT, true);
276 }
277 LambdaForm(String debugName,
278 Name[] formals, Name[] temps, Name result, boolean forceInline) {
279 this(debugName,
280 formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline);
281 }
282
283 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
284 int arity = formals.length;
285 int length = arity + temps.length + (result == null ? 0 : 1);
286 Name[] names = Arrays.copyOf(formals, length);
287 System.arraycopy(temps, 0, names, arity, temps.length);
288 if (result != null)
289 names[length - 1] = result;
290 return names;
291 }
292
293 private LambdaForm(String sig) {
294 this(sig, true);
295 }
296
297 private LambdaForm(String sig, boolean forceInline) {
298 // Make a blank lambda form, which returns a constant zero or null.
299 // It is used as a template for managing the invocation of similar forms that are non-empty.
300 // Called only from getPreparedForm.
301 assert(isValidSignature(sig));
302 this.arity = signatureArity(sig);
303 this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
304 this.names = buildEmptyNames(arity, sig);
305 this.debugName = "LF.zero";
306 this.forceInline = forceInline;
307 assert(nameRefsAreLegal());
308 assert(isEmpty());
309 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
310 }
311
312 private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
313 assert(isValidSignature(basicTypeSignature));
314 int resultPos = arity + 1; // skip '_'
315 if (arity < 0 || basicTypeSignature.length() != resultPos+1)
316 throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
317 int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
318 Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
319 for (int i = 0; i < numRes; i++) {
320 Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
321 names[arity + i] = zero.newIndex(arity + i);
322 }
323 return names;
324 }
325
326 private static int fixResult(int result, Name[] names) {
1778 private static void zero_V() { return; }
1779
1780 /**
1781 * Internal marker for byte-compiled LambdaForms.
1782 */
1783 /*non-public*/
1784 @Target(ElementType.METHOD)
1785 @Retention(RetentionPolicy.RUNTIME)
1786 @interface Compiled {
1787 }
1788
1789 /**
1790 * Internal marker for LambdaForm interpreter frames.
1791 */
1792 /*non-public*/
1793 @Target(ElementType.METHOD)
1794 @Retention(RetentionPolicy.RUNTIME)
1795 @interface Hidden {
1796 }
1797
1798 private static final HashMap<String,Integer> DEBUG_NAME_COUNTERS;
1799 static {
1800 if (debugEnabled())
1801 DEBUG_NAME_COUNTERS = new HashMap<>();
1802 else
1803 DEBUG_NAME_COUNTERS = null;
1804 }
1805
1806 // Put this last, so that previous static inits can run before.
1807 static {
1808 createIdentityForms();
1809 if (USE_PREDEFINED_INTERPRET_METHODS)
1810 computeInitialPreparedForms();
1811 NamedFunction.initializeInvokers();
1812 }
1813
1814 // The following hack is necessary in order to suppress TRACE_INTERPRETER
1815 // during execution of the static initializes of this class.
1816 // Turning on TRACE_INTERPRETER too early will cause
1817 // stack overflows and other misbehavior during attempts to trace events
|
103 * t3:L = MethodHandle#invoke(t2, a1);
104 * t4:L = FilterMethodHandle#target(a0);
105 * t5:L = MethodHandle#invoke(t4, t3); t5 }
106 * == general invoker for unary filterArgument combination
107 * (a0:L, a1:L)=>{ ...(same as previous example)...
108 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
109 * == general invoker for unary/unary foldArgument combination
110 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
111 * == invoker for identity method handle which performs i2l
112 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
113 * t3:L = Class#cast(t2,a1); t3 }
114 * == invoker for identity method handle which performs cast
115 * }</pre></blockquote>
116 * <p>
117 * @author John Rose, JSR 292 EG
118 */
119 class LambdaForm {
120 final int arity;
121 final int result;
122 final boolean forceInline;
123 final boolean isGWT;
124 @Stable final Name[] names;
125 final String debugName;
126 MemberName vmentry; // low-level behavior, or null if not yet prepared
127 private boolean isCompiled;
128
129 Object transformCache; // managed by LambdaFormEditor
130
131 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
132
133 enum BasicType {
134 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
135 I_TYPE('I', int.class, Wrapper.INT),
136 J_TYPE('J', long.class, Wrapper.LONG),
137 F_TYPE('F', float.class, Wrapper.FLOAT),
138 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
139 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
140
141 static final BasicType[] ALL_TYPES = BasicType.values();
142 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
143
228 return "LIJFD".indexOf(c) >= 0;
229 }
230
231 static { assert(checkBasicType()); }
232 private static boolean checkBasicType() {
233 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
234 assert ARG_TYPES[i].ordinal() == i;
235 assert ARG_TYPES[i] == ALL_TYPES[i];
236 }
237 for (int i = 0; i < TYPE_LIMIT; i++) {
238 assert ALL_TYPES[i].ordinal() == i;
239 }
240 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
241 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
242 return true;
243 }
244 }
245
246 LambdaForm(String debugName,
247 int arity, Name[] names, int result) {
248 this(debugName, arity, names, result, /*forceInline=*/true, /*isGWT=*/false);
249 }
250 LambdaForm(String debugName,
251 int arity, Name[] names, int result, boolean forceInline, boolean isGWT) {
252 assert(namesOK(arity, names));
253 this.arity = arity;
254 this.result = fixResult(result, names);
255 this.names = names.clone();
256 this.debugName = fixDebugName(debugName);
257 this.forceInline = forceInline;
258 this.isGWT = isGWT;
259 int maxOutArity = normalize();
260 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
261 // Cannot use LF interpreter on very high arity expressions.
262 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
263 compileToBytecode();
264 }
265 }
266 LambdaForm(String debugName,
267 int arity, Name[] names) {
268 this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*isGWT=*/false);
269 }
270 LambdaForm(String debugName,
271 int arity, Name[] names, boolean forceInline, boolean isGWT) {
272 this(debugName, arity, names, LAST_RESULT, forceInline, isGWT);
273 }
274 LambdaForm(String debugName,
275 Name[] formals, Name[] temps, Name result) {
276 this(debugName,
277 formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*isGWT=*/false);
278 }
279 LambdaForm(String debugName,
280 Name[] formals, Name[] temps, Name result, boolean forceInline) {
281 this(debugName,
282 formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*isGWT=*/false);
283 }
284
285 static LambdaForm makeGuardWithTestForm(int paramCount, Name[] names) {
286 return new LambdaForm("guard", paramCount, names, /*forceInline=*/true, /*isGWT=*/true);
287 }
288
289 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
290 int arity = formals.length;
291 int length = arity + temps.length + (result == null ? 0 : 1);
292 Name[] names = Arrays.copyOf(formals, length);
293 System.arraycopy(temps, 0, names, arity, temps.length);
294 if (result != null)
295 names[length - 1] = result;
296 return names;
297 }
298
299 private LambdaForm(String sig) {
300 // Make a blank lambda form, which returns a constant zero or null.
301 // It is used as a template for managing the invocation of similar forms that are non-empty.
302 // Called only from getPreparedForm.
303 assert(isValidSignature(sig));
304 this.arity = signatureArity(sig);
305 this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
306 this.names = buildEmptyNames(arity, sig);
307 this.debugName = "LF.zero";
308 this.forceInline = true;
309 this.isGWT = false;
310 assert(nameRefsAreLegal());
311 assert(isEmpty());
312 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
313 }
314
315 private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
316 assert(isValidSignature(basicTypeSignature));
317 int resultPos = arity + 1; // skip '_'
318 if (arity < 0 || basicTypeSignature.length() != resultPos+1)
319 throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
320 int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
321 Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
322 for (int i = 0; i < numRes; i++) {
323 Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
324 names[arity + i] = zero.newIndex(arity + i);
325 }
326 return names;
327 }
328
329 private static int fixResult(int result, Name[] names) {
1781 private static void zero_V() { return; }
1782
1783 /**
1784 * Internal marker for byte-compiled LambdaForms.
1785 */
1786 /*non-public*/
1787 @Target(ElementType.METHOD)
1788 @Retention(RetentionPolicy.RUNTIME)
1789 @interface Compiled {
1790 }
1791
1792 /**
1793 * Internal marker for LambdaForm interpreter frames.
1794 */
1795 /*non-public*/
1796 @Target(ElementType.METHOD)
1797 @Retention(RetentionPolicy.RUNTIME)
1798 @interface Hidden {
1799 }
1800
1801 /**
1802 * Internal marker which signals JIT that gathered profile is useless.
1803 */
1804 /*non-public*/
1805 @Target(ElementType.METHOD)
1806 @Retention(RetentionPolicy.RUNTIME)
1807 @interface IgnoreProfile {
1808 }
1809
1810 private static final HashMap<String,Integer> DEBUG_NAME_COUNTERS;
1811 static {
1812 if (debugEnabled())
1813 DEBUG_NAME_COUNTERS = new HashMap<>();
1814 else
1815 DEBUG_NAME_COUNTERS = null;
1816 }
1817
1818 // Put this last, so that previous static inits can run before.
1819 static {
1820 createIdentityForms();
1821 if (USE_PREDEFINED_INTERPRET_METHODS)
1822 computeInitialPreparedForms();
1823 NamedFunction.initializeInvokers();
1824 }
1825
1826 // The following hack is necessary in order to suppress TRACE_INTERPRETER
1827 // during execution of the static initializes of this class.
1828 // Turning on TRACE_INTERPRETER too early will cause
1829 // stack overflows and other misbehavior during attempts to trace events
|