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

Print this page




 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         }