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 @Stable final Name[] names;
123 final String debugName;
124 MemberName vmentry; // low-level behavior, or null if not yet prepared
125 private boolean isCompiled;
126
127 Object transformCache; // managed by LambdaFormEditor
128
129 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
130
131 enum BasicType {
132 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
133 I_TYPE('I', int.class, Wrapper.INT),
134 J_TYPE('J', long.class, Wrapper.LONG),
135 F_TYPE('F', float.class, Wrapper.FLOAT),
136 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
137 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
138
139 static final BasicType[] ALL_TYPES = BasicType.values();
140 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
141
142 static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
143 static final int TYPE_LIMIT = ALL_TYPES.length;
144
145 private final char btChar;
146 private final Class<?> btClass;
147 private final Wrapper btWrapper;
224 }
225 static boolean isArgBasicTypeChar(char c) {
226 return "LIJFD".indexOf(c) >= 0;
227 }
228
229 static { assert(checkBasicType()); }
230 private static boolean checkBasicType() {
231 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
232 assert ARG_TYPES[i].ordinal() == i;
233 assert ARG_TYPES[i] == ALL_TYPES[i];
234 }
235 for (int i = 0; i < TYPE_LIMIT; i++) {
236 assert ALL_TYPES[i].ordinal() == i;
237 }
238 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
239 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
240 return true;
241 }
242 }
243
244 LambdaForm(String debugName,
245 int arity, Name[] names, int result) {
246 assert(namesOK(arity, names));
247 this.arity = arity;
248 this.result = fixResult(result, names);
249 this.names = names.clone();
250 this.debugName = fixDebugName(debugName);
251 int maxOutArity = normalize();
252 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
253 // Cannot use LF interpreter on very high arity expressions.
254 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
255 compileToBytecode();
256 }
257 }
258
259 LambdaForm(String debugName,
260 int arity, Name[] names) {
261 this(debugName,
262 arity, names, LAST_RESULT);
263 }
264
265 LambdaForm(String debugName,
266 Name[] formals, Name[] temps, Name result) {
267 this(debugName,
268 formals.length, buildNames(formals, temps, result), LAST_RESULT);
269 }
270
271 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
272 int arity = formals.length;
273 int length = arity + temps.length + (result == null ? 0 : 1);
274 Name[] names = Arrays.copyOf(formals, length);
275 System.arraycopy(temps, 0, names, arity, temps.length);
276 if (result != null)
277 names[length - 1] = result;
278 return names;
279 }
280
281 private LambdaForm(String sig) {
282 // Make a blank lambda form, which returns a constant zero or null.
283 // It is used as a template for managing the invocation of similar forms that are non-empty.
284 // Called only from getPreparedForm.
285 assert(isValidSignature(sig));
286 this.arity = signatureArity(sig);
287 this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
288 this.names = buildEmptyNames(arity, sig);
289 this.debugName = "LF.zero";
290 assert(nameRefsAreLegal());
291 assert(isEmpty());
292 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
293 }
294
295 private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
296 assert(isValidSignature(basicTypeSignature));
297 int resultPos = arity + 1; // skip '_'
298 if (arity < 0 || basicTypeSignature.length() != resultPos+1)
299 throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
300 int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
301 Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
302 for (int i = 0; i < numRes; i++) {
303 Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
304 names[arity + i] = zero.newIndex(arity + i);
305 }
|
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 @Stable final Name[] names;
123 final String debugName;
124 MemberName vmentry; // low-level behavior, or null if not yet prepared
125 private boolean isCompiled;
126
127 volatile Object transformCache; // managed by LambdaFormEditor
128
129 // non-null only if this is a derived LF that is cached in
130 // baseLambdaForm.transformCache. this is necessary so that base LF
131 // this LF was derived from is not GC-ed for as long as this LF is retained.
132 // no program logic is dependent on this field. just GC.
133 private final LambdaForm baseLambdaForm;
134
135 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
136
137 enum BasicType {
138 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
139 I_TYPE('I', int.class, Wrapper.INT),
140 J_TYPE('J', long.class, Wrapper.LONG),
141 F_TYPE('F', float.class, Wrapper.FLOAT),
142 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
143 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
144
145 static final BasicType[] ALL_TYPES = BasicType.values();
146 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
147
148 static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
149 static final int TYPE_LIMIT = ALL_TYPES.length;
150
151 private final char btChar;
152 private final Class<?> btClass;
153 private final Wrapper btWrapper;
230 }
231 static boolean isArgBasicTypeChar(char c) {
232 return "LIJFD".indexOf(c) >= 0;
233 }
234
235 static { assert(checkBasicType()); }
236 private static boolean checkBasicType() {
237 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
238 assert ARG_TYPES[i].ordinal() == i;
239 assert ARG_TYPES[i] == ALL_TYPES[i];
240 }
241 for (int i = 0; i < TYPE_LIMIT; i++) {
242 assert ALL_TYPES[i].ordinal() == i;
243 }
244 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
245 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
246 return true;
247 }
248 }
249
250 LambdaForm(LambdaForm baseLambdaForm, String debugName,
251 int arity, Name[] names, int result) {
252 assert(namesOK(arity, names));
253 this.baseLambdaForm = baseLambdaForm;
254 this.arity = arity;
255 this.result = fixResult(result, names);
256 this.names = names.clone();
257 this.debugName = fixDebugName(debugName);
258 int maxOutArity = normalize();
259 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
260 // Cannot use LF interpreter on very high arity expressions.
261 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
262 compileToBytecode();
263 }
264 }
265
266 LambdaForm(String debugName,
267 int arity, Name[] names, int result) {
268 this(null, debugName, arity, names, result);
269 }
270
271 LambdaForm(String debugName,
272 int arity, Name[] names) {
273 this(debugName,
274 arity, names, LAST_RESULT);
275 }
276
277 LambdaForm(String debugName,
278 Name[] formals, Name[] temps, Name result) {
279 this(debugName,
280 formals.length, buildNames(formals, temps, result), LAST_RESULT);
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 // Make a blank lambda form, which returns a constant zero or null.
295 // It is used as a template for managing the invocation of similar forms that are non-empty.
296 // Called only from getPreparedForm.
297 assert(isValidSignature(sig));
298 this.baseLambdaForm = null;
299 this.arity = signatureArity(sig);
300 this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
301 this.names = buildEmptyNames(arity, sig);
302 this.debugName = "LF.zero";
303 assert(nameRefsAreLegal());
304 assert(isEmpty());
305 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
306 }
307
308 private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
309 assert(isValidSignature(basicTypeSignature));
310 int resultPos = arity + 1; // skip '_'
311 if (arity < 0 || basicTypeSignature.length() != resultPos+1)
312 throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
313 int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
314 Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
315 for (int i = 0; i < numRes; i++) {
316 Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
317 names[arity + i] = zero.newIndex(arity + i);
318 }
|